home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume9 / zmac / part01 next >
Encoding:
Internet Message Format  |  1987-03-11  |  56.0 KB

  1. Subject:  v09i024:  Z80 macro cross-assembler, Part01/02
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.TMC.COM
  4.  
  5. Submitted by: pyrnj!vu-vlsi!colin (Colin Kelley)
  6. Mod.sources: Volume 9, Issue 24
  7. Archive-name: zmac/Part01
  8.  
  9. #! /bin/sh
  10. # This is a shell archive, meaning:
  11. # 1. Remove everything above the #! /bin/sh line.
  12. # 2. Save the resulting text in a file.
  13. # 3. Execute the file with /bin/sh (not csh) to create the files:
  14. #    Makefile zmac.y mio.c zmac.1 zdis.1
  15. export PATH; PATH=/bin:$PATH
  16. echo shar: extracting "'Makefile'" '(642 characters)'
  17. if test -f 'Makefile'
  18. then
  19.     echo shar: will not over-write existing file "'Makefile'"
  20. else
  21. cat << \SHAR_EOF > 'Makefile'
  22. # Makefile to make z80 macro assembler.
  23. CFLAGS =
  24.  
  25. all:    zmac zdis
  26.  
  27. zmac:    y.tab.o mio.o
  28.     cc $(CFLAGS) -o zmac y.tab.o mio.o
  29.  
  30. y.tab.c: zmac.y
  31.     yacc zmac.y
  32.  
  33. zdis:    zdis.o
  34.     cc $(CFLAGS) -o zdis zdis.o
  35.  
  36. install:
  37.     install -s zmac /usr/local/bin
  38.     install -s zdis /usr/local/bin
  39.  
  40. install_man:
  41.     cp zmac.1 /usr/man/manl/zmac.l
  42.     cp zdis.1 /usr/man/manl/zdis.l
  43.  
  44. clean:
  45.     rm -f zdis.o zmac.o mio.o y.tab.c y.tab.o a.out core
  46.  
  47. shar: zmac.shar.1 zmac.shar.2
  48.  
  49. zmac.shar.1: Makefile zmac.y mio.c zmac.1 zdis.1
  50.     shar -vc Makefile zmac.y mio.c zmac.1 zdis.1 > zmac.shar.1
  51.  
  52. zmac.shar.2: zdis.c serial.z serial.hex
  53.     shar -vc zdis.c serial.z serial.hex > zmac.shar.2
  54. SHAR_EOF
  55. if test 642 -ne "`wc -c < 'Makefile'`"
  56. then
  57.     echo shar: error transmitting "'Makefile'" '(should have been 642 characters)'
  58. fi
  59. chmod +x 'Makefile'
  60. fi # end of overwriting check
  61. echo shar: extracting "'zmac.y'" '(50295 characters)'
  62. if test -f 'zmac.y'
  63. then
  64.     echo shar: will not over-write existing file "'zmac.y'"
  65. else
  66. cat << \SHAR_EOF > 'zmac.y'
  67. %{
  68. /*
  69.  *  zmac -- macro cross-assembler for the Zilog Z80 microprocessor
  70.  *
  71.  *  Bruce Norskog    4/78
  72.  *
  73.  *  Last modification  1-18-87 by cdk
  74.  *  This assembler is modeled after the Intel 8080 macro cross-assembler
  75.  *  for the Intel 8080 by Ken Borgendale.  The major features are:
  76.  *    1.  Full macro capabilities
  77.  *    2.  Conditional assembly
  78.  *    3.  A very flexible set of listing options and pseudo-ops
  79.  *    4.  Symbol table output
  80.  *    5.  Error report
  81.  *    6.  Elimination of sequential searching
  82.  *    7.  Commenting of source
  83.  *    8.  Facilities for system definiton files
  84.  *
  85.  * Revision History:
  86.  *
  87.  * jrp    3-8-82    Converted to run on Vax, updated syntax to conform better
  88.  *        to the Zilog standard.
  89.  *
  90.  * jrp    3-15-82    Added underscore as a character type in the lex table
  91.  *        'numpart' (0x5F).
  92.  *
  93.  *        Changed maximum number of characters in a label to 15
  94.  *        from 7. Note that 'putsymtab' uses this value inside
  95.  *        of a quoted string, so we use 15.
  96.  *
  97.  * jrp    2-15-83    Fixed 'getlocal' to return better local labels. It used
  98.  *        to crash after 6 invocations.
  99.  *
  100.  * jrp    6-7-83    Fixed bug in the ADD IX,... instruction.
  101.  *
  102.  * jrp    5-11-84    Added code to print unused labels out with the symbol table
  103.  *        Also sped up the macro processor by using stdio.
  104.  *
  105.  * jrp 5-22-84    Added include files ala ormac
  106.  *
  107.  * jrp 8-27-84    Added PHASE/DEPHASE commands
  108.  *
  109.  * cdk 9-20-86    Converted to run on a Pyramid.  This meant changing yylval
  110.  *        to be a %union, and then putting in the appropriate
  111.  *        typecasts where ints are pointers are used interchangeably.
  112.  *        The current version still probably won't run on machines where
  113.  *        sizeof(int) != sizeof(char *).
  114.  *        Also changed emit() to use varargs, and got rid of the
  115.  *        old style = in front of yacc action code.
  116.  *            -Colin Kelley  vu-vlsi!colin
  117.  *
  118.  * cdk 10-2-86    Added some more typecasts to keep lint a little happier.
  119.  *        Removed several unused variables.  Changed most vars
  120.  *        declared as char to int, since many of them were being
  121.  *        compared with -1!  I still don't know what's going on with
  122.  *        est[][] being malloc'd and free'd everywhere...it looks pretty
  123.  *        fishy...
  124.  *
  125.  * cdk 1-18-87  Added MIO code to emulate 'mfile' using malloc()'d memory.
  126.  *        This was needed to get the code to work when compiled under
  127.  *        MSC 4.0 on a PC, and it's probably faster anyway.
  128.  *
  129.  * cdk 2-5-87    Added 'cmp' as a synonym for 'cp', 'jmp' as a synonym for
  130.  *        'jp', and added tolerance of accumulator specification for arithmetic
  131.  *        and logical instructions.  (For example, 'or a,12' is now accepted,
  132.  *        same as 'or 12'.)
  133.  */
  134.  
  135.  
  136. #define MIO        /* use emulation routines from mio.c */
  137.  
  138. #include <stdio.h>
  139. #ifdef MSDOS
  140. #include <fcntl.h>
  141. #else
  142. #include <sys/file.h>    /* for open() calls */
  143. #endif
  144.  
  145. #ifdef vax11c
  146. #define unlink(filename) delete(filename)
  147. #endif
  148.  
  149. #ifdef MIO
  150. FILE *mfopen();
  151. #else
  152. #define mfopen(filename,mode) fopen(filename,mode)
  153. #define mfclose(filename,mode) fclose(filename,mode) 
  154. #define mfputc(c,f) putc(c,f)
  155. #define mfgetc(f) getc(f)
  156. #define mfseek(f,loc,origin) fseek(f,loc,origin)
  157. #define mfread(ptr,size,nitems,f) fread(ptr,size,nitems,f)
  158. #define mfwrite(ptr,size,nitems,f) fread(ptr,size,nitems,f)
  159. #endif /* MIO */
  160.  
  161. /*
  162.  * DEBUG turns on pass reporting.
  163.  * Macro debug and Token debug enables.
  164. #define    DEBUG
  165. #define    M_DEBUG    
  166. #define    T_DEBUG
  167.  */
  168.  
  169. #define ITEMTABLESIZE    2000
  170. #define TEMPBUFSIZE    200
  171. #define LINEBUFFERSIZE    200
  172. #define EMITBUFFERSIZE    200
  173. #define MAXSYMBOLSIZE    15
  174. #define IFSTACKSIZE    20
  175. #define MAXIFS        150
  176. #define TITLELEN    50
  177. #define BINPERLINE    16
  178. #define    PARMMAX        25
  179. #define MAXEXP        25
  180. #define SYMMAJIC    07203
  181. #define    NEST_IN        8
  182.  
  183.  
  184. #define loop    for(;;)
  185.  
  186. yyerror(err)
  187. char *err;
  188. {}        /* we will do our own error printing */
  189.  
  190. struct    item    {
  191.     char    *i_string;
  192.     int    i_value;
  193.     int    i_token;
  194.     int    i_uses;
  195. };
  196.  
  197. FILE    *fout,
  198.     *fbuf,
  199.     *fin[NEST_IN],
  200.     *now_file ;
  201.  
  202. char *malloc() ;
  203.  
  204. int    pass2;    /*set when pass one completed*/
  205. int    dollarsign ;    /* location counter */
  206. int    olddollar ;    /* kept to put out binary */
  207.  
  208. /* program counter save for PHASE/DEPHASE */
  209. int    phdollar, phbegin, phaseflag ;
  210.  
  211. char    *src_name[NEST_IN] ;
  212. int    linein[NEST_IN] ;
  213. int    now_in ;
  214.  
  215.  
  216.  
  217. #define bflag    0    /* balance error */
  218. #define eflag    1    /* expression error */
  219. #define fflag    2    /* format error */
  220. #define iflag    3    /* bad digits */
  221. #define mflag    4    /* multiply defined */
  222. #define pflag    5    /* phase error */
  223. #define uflag    6    /* undeclared used */
  224. #define vflag    7    /* value out of range */
  225. #define oflag    8    /* phase/dephase error */
  226.  
  227. #define FLAGS    9    /* number of flags */
  228.  
  229. char    err[FLAGS];
  230. int    keeperr[FLAGS];
  231. char    errlet[]="BEFIMPUVO";
  232. char    *errname[]={
  233.     "Balance",
  234.     "Expression",
  235.     "Format",
  236.     "Digit",
  237.     "Mult. def.",
  238.     "Phase",
  239.     "Undeclared",
  240.     "Value",
  241.     "Phase/Dephase",
  242. };
  243.  
  244.  
  245. char    linebuf[LINEBUFFERSIZE];
  246. char    *lineptr;
  247. char    *linemax = &linebuf[LINEBUFFERSIZE];
  248.  
  249. char    outbin[BINPERLINE];
  250. char    *outbinp = outbin;
  251. char    *outbinm = &outbin[BINPERLINE];
  252.  
  253. char    emitbuf[EMITBUFFERSIZE];
  254. char    *emitptr;
  255.  
  256. char    ifstack[IFSTACKSIZE];
  257. char    *ifptr;
  258. char    *ifstmax = &ifstack[IFSTACKSIZE-1];
  259.  
  260.  
  261. char    expif[MAXIFS];
  262. char    *expifp;
  263. char    *expifmax = &expif[MAXIFS];
  264.  
  265. char    hexadec[] = "0123456789ABCDEF" ;
  266. char    *expstack[MAXEXP];
  267. int    expptr;
  268.  
  269.  
  270. int    nitems;
  271. int    linecnt;
  272. int    nbytes;
  273. int    invented;
  274.  
  275.  
  276. char    tempbuf[TEMPBUFSIZE];
  277. char    *tempmax = &tempbuf[TEMPBUFSIZE-1];
  278.  
  279. char    inmlex;
  280. char    arg_flag;
  281. char    quoteflag;
  282. int    parm_number;
  283. int    exp_number;
  284. char    symlong[] = "Symbol too long";
  285.  
  286. int    disp;
  287. #define FLOC    PARMMAX
  288. #define TEMPNUM    PARMMAX+1
  289. char    **est;
  290. char    **est2;
  291.  
  292. char    *floc;
  293. int    mfptr;
  294. FILE    *mfile;
  295.  
  296. char    *writesyms;
  297.  
  298.  
  299. char    *title;
  300. char    titlespace[TITLELEN];
  301. char    *timp,*ctime();
  302. char    *sourcef;
  303. char    src[15];
  304. char    bin[15];
  305. char    mtmp[15];
  306. char    listf[15];
  307.  
  308. char    bopt = 1,
  309.     edef = 1,
  310.     eopt = 1,
  311.     fdef = 0,
  312.     fopt = 0,
  313.     gdef = 1,
  314.     gopt = 1,
  315.     iopt = 0 ,    /* list include files */
  316.     lstoff = 0,
  317.     lston = 0,    /* flag to force listing on */
  318.     lopt = 0,
  319.     mdef = 0,
  320.     mopt = 0,
  321.     nopt = 1 ,    /* line numbers on as default */
  322.     oopt = 0,
  323.     popt = 1,    /* form feed as default page eject */
  324.     sopt = 0,    /* turn on symbol table listing */
  325.     topt = 1;
  326.     saveopt;
  327.  
  328. char    xeq_flag = 0;
  329. int    xeq;
  330.  
  331. long    now;
  332. int    line;
  333. int    page = 1;
  334.  
  335. struct stab {
  336.     char    t_name[MAXSYMBOLSIZE+1];
  337.     int    t_value;
  338.     int    t_token;
  339. };
  340.  
  341. /*
  342.  *  push back character
  343.  */
  344. int    peekc;
  345.  
  346.  
  347. /*
  348.  *  add a character to the output line buffer
  349.  */
  350. addtoline(ac)
  351. int    ac;
  352. {
  353.     /* check for EOF from stdio */
  354.     if (ac == -1)
  355.         ac = 0 ;
  356.     if (inmlex)
  357.         return(ac);
  358.     if (lineptr >= linemax)
  359.         error("line buffer overflow");
  360.     *lineptr++ = ac;
  361.     return(ac);
  362. }
  363.  
  364. #include <varargs.h>
  365.  
  366. /*
  367.  *  put values in buffer for outputing
  368.  */
  369.  
  370. /*VARARGS*/
  371. /*ARGSUSED*/
  372. emit(va_alist)
  373. va_dcl
  374. {    
  375.     register int bytes;
  376.     va_list ap;
  377.     va_start(ap);
  378.  
  379.     bytes = va_arg(ap,int);
  380.  
  381.     while    (--bytes >= 0)
  382.         if (emitptr >= &emitbuf[EMITBUFFERSIZE])
  383.             error("emit buffer overflow");
  384.         else {
  385.             *emitptr++ = va_arg(ap,int);
  386.         }
  387.     va_end(ap);
  388. }
  389.  
  390.  
  391. emit1(opcode,regvalh,data16,type)
  392. int    opcode,regvalh,data16,type;
  393. {
  394.     if (regvalh & 0x8000) {
  395.         if (type & 1 == 0 && (disp > 127 || disp < -128))
  396.             err[vflag]++;
  397.         switch(type) {
  398.         case 0:
  399.             if (opcode & 0x8000)
  400.                 emit(4, regvalh >> 8, opcode >> 8, disp, opcode);
  401.             else
  402.                 emit(3, regvalh >> 8, opcode, disp);
  403.             break;
  404.         case 1:
  405.             emit(2, regvalh >> 8, opcode);
  406.             break;
  407.         case 2:
  408.             if (data16 > 255 || data16 < -128)
  409.                 err[vflag]++;
  410.             emit(4, regvalh >> 8, opcode, disp, data16);
  411.             break;
  412.         case 5:
  413.             emit(4, regvalh >> 8, opcode, data16, data16 >> 8);
  414.         }
  415.     } else
  416.         switch(type) {
  417.         case 0:
  418.             if (opcode & 0100000)
  419.                 emit(2, opcode >> 8, opcode);
  420.             else
  421.                 emit(1, opcode);
  422.             break;
  423.         case 1:
  424.             if (opcode & 0100000)
  425.                 emit(2, opcode >> 8, opcode);
  426.             else
  427.                 emit(1, opcode);
  428.             break;
  429.         case 2:
  430.             if (data16 > 255 || data16 < -128)
  431.                 err[vflag]++;
  432.             emit(2, opcode, data16);
  433.             break;
  434.         case 3:
  435.             if (data16 >255 || data16 < -128)
  436.                 err[vflag]++;
  437.             emit(2, opcode, data16);
  438.             break;
  439.         case 5:
  440.             if (opcode & 0100000)
  441.                 emit(4, opcode >> 8, opcode, data16, data16 >> 8);
  442.             else
  443.                 emit(3, opcode, data16, data16 >> 8);
  444.         }
  445. }
  446.  
  447.  
  448.  
  449.  
  450. emitdad(rp1,rp2)
  451. int rp1,rp2;
  452. {
  453.     if (rp1 & 0x8000)
  454.         emit(2,rp1 >> 8, rp2 + 9);
  455.     else
  456.         emit(1,rp2 + 9);
  457. }
  458.  
  459.  
  460. emitjr(opcode,expr)
  461. int    opcode,expr;
  462. {
  463.     disp = expr - dollarsign - 2;
  464.     if (disp > 127 || disp < -128)
  465.         err[vflag]++;
  466.     emit(2, opcode, disp);
  467. }
  468.  
  469.  
  470.  
  471.  
  472. /*
  473.  *  put out a byte of binary 
  474.  */
  475. putbin(v)
  476. {
  477.     if(!pass2 || !bopt) return;
  478.     *outbinp++ = v;
  479.     if (outbinp >= outbinm) flushbin();
  480. }
  481.  
  482.  
  483.  
  484. /*
  485.  *  output one line of binary in INTEL standard form
  486.  */
  487. flushbin()
  488. {
  489.     register  char *p;
  490.     register check;
  491.  
  492.     if (!pass2 || !bopt)
  493.         return;
  494.     nbytes += outbinp-outbin;
  495.     if (check = outbinp-outbin) {
  496.         putc(':', fbuf);
  497.         puthex(check, fbuf);
  498.         puthex(olddollar>>8, fbuf);
  499.         puthex(olddollar, fbuf);
  500.         puthex(0, fbuf);
  501.         check += (olddollar >> 8) + olddollar;
  502.         olddollar += (outbinp-outbin);
  503.         for (p=outbin; p<outbinp; p++) {
  504.             puthex(*p, fbuf);
  505.             check += *p;
  506.         }
  507.         puthex(256-check, fbuf);
  508.         putc('\n', fbuf);
  509.         outbinp = outbin;
  510.     }
  511. }
  512.  
  513.  
  514.  
  515. /*
  516.  *  put out one byte of hex
  517.  */
  518. puthex(byte, buf)
  519. char    byte;
  520. FILE    *buf;
  521. {
  522.     putc(hexadec[(byte >> 4) & 017], buf);
  523.     putc(hexadec[byte & 017], buf);
  524. }
  525.  
  526. /*
  527.  *  put out a line of output -- also put out binary
  528.  */
  529. list(optarg)
  530. int    optarg;
  531. {
  532.     register char *    p;
  533.     register int    i;
  534.     int  lst;
  535.  
  536.     if (!expptr)
  537.         linecnt++;
  538.     addtoline('\0');
  539.     if (pass2) {
  540.         lst = iflist();
  541.         if (lst) {
  542.             lineout();
  543.             if (nopt)
  544.                 fprintf(fout, "%4d:\t", linein[now_in]);
  545.             puthex(optarg >> 8, fout);
  546.             puthex(optarg, fout);
  547.             fputs("  ", fout);
  548.             for (p = emitbuf; (p < emitptr) && (p - emitbuf < 4); p++) {
  549.                 puthex(*p, fout);
  550.             }
  551.             for (i = 4 - (p-emitbuf); i > 0; i--)
  552.                 fputs("  ", fout);
  553.             putc('\t', fout);
  554.             fputs(linebuf, fout);
  555.         }
  556.  
  557.         if (bopt) {
  558.             for (p = emitbuf; p < emitptr; p++)
  559.                 putbin(*p);
  560.         }
  561.  
  562.  
  563.         p = emitbuf+4;
  564.         while (lst && gopt && p < emitptr) {
  565.             lineout();
  566.             if (nopt) putc('\t', fout);
  567.             fputs("      ", fout);
  568.             for (i = 0; (i < 4) && (p < emitptr);i++) {
  569.                 puthex(*p, fout);
  570.                 p++;
  571.             }
  572.             putc('\n', fout);
  573.         }
  574.  
  575.  
  576.         lsterr2(lst);
  577.     } else
  578.         lsterr1();
  579.     dollarsign += emitptr - emitbuf;
  580.     emitptr = emitbuf;
  581.     lineptr = linebuf;
  582. }
  583.  
  584.  
  585.  
  586. /*
  587.  *  keep track of line numbers and put out headers as necessary
  588.  */
  589. lineout()
  590. {
  591.     if (line == 60) {
  592.         if (popt)
  593.             putc('\014', fout);    /* send the form feed */
  594.         else
  595.             fputs("\n\n\n\n\n", fout);
  596.         line = 0;
  597.     }
  598.     if (line == 0) {
  599.         fprintf(fout, "\n\n%s %s\t%s\t Page %d\n\n\n",
  600.             &timp[4], &timp[20], title, page++);
  601.         line = 4;
  602.     }
  603.     line++;
  604. }
  605.  
  606.  
  607. /*
  608.  *  cause a page eject
  609.  */
  610. eject()
  611. {
  612.     if (pass2 && iflist()) {
  613.         if (popt) {
  614.             putc('\014', fout);    /* send the form feed */
  615.         } else {
  616.             while (line < 65) {
  617.                 line++;
  618.                 putc('\n', fout);
  619.             }
  620.         }
  621.     }
  622.     line = 0;
  623. }
  624.  
  625.  
  626. /*
  627.  *  space n lines on the list file
  628.  */
  629. space(n)
  630. {
  631.     int    i ;
  632.     if (pass2 && iflist())
  633.         for (i = 0; i<n; i++) {
  634.             lineout();
  635.             putc('\n', fout);
  636.         }
  637. }
  638.  
  639.  
  640. /*
  641.  *  Error handling - pass 1
  642.  */
  643. lsterr1() {
  644.     register int i;
  645.     if (topt)
  646.         for (i = 0; i <= 4; i++)
  647.             if (err[i]) {
  648.                 errorprt(i);
  649.                 err[i] = 0;
  650.             }
  651. }
  652.  
  653.  
  654. /*
  655.  *  Error handling - pass 2.
  656.  */
  657. lsterr2(lst)
  658. int    lst;
  659. {
  660.     register int i;
  661.     for (i=0; i<FLAGS; i++)
  662.         if (err[i]) {
  663.             if (lst) {
  664.                 lineout();
  665.                 putc(errlet[i], fout);
  666.                 putc('\n', fout);
  667.             }
  668.             err[i] = 0;
  669.             keeperr[i]++;
  670.             if (i > 4 && topt)
  671.                 errorprt(i);
  672.         }
  673.  
  674.     fflush(fout);    /*to avoid putc(har) mix bug*/
  675. }
  676.  
  677. /*
  678.  *  print diagnostic to error terminal
  679.  */
  680. errorprt(errnum)
  681. int    errnum;
  682. {
  683.     fprintf(stderr,"%d: %s error\n%s\n",
  684.         linecnt, errname[errnum], linebuf) ;
  685.     fflush(stderr) ;
  686.     return ;
  687. }
  688.  
  689.  
  690. /*
  691.  *  list without address -- for comments and if skipped lines
  692.  */
  693. list1()
  694. {
  695.     int lst;
  696.  
  697.     addtoline('\0');
  698.     lineptr = linebuf;
  699.     if (!expptr) linecnt++;
  700.     if (pass2)
  701.         if (lst = iflist()) {
  702.             lineout();
  703.             if (nopt)
  704.                 fprintf(fout, "%4d:\t", linein[now_in]);
  705.             fprintf(fout, "\t\t%s", linebuf);
  706.             lsterr2(lst);
  707.         }
  708.     else
  709.         lsterr1();
  710. }
  711.  
  712.  
  713. /*
  714.  *  see if listing is desired
  715.  */
  716. iflist()
  717. {
  718.     register  i, j;
  719.  
  720.     if (lston)
  721.         return(1) ;
  722.     if (lopt)
  723.         return(0);
  724.     if (*ifptr && !fopt)
  725.         return(0);
  726.     if (!lstoff && !expptr)
  727.         return(1);
  728.     j = 0;
  729.     for (i=0; i<FLAGS; i++)
  730.         if (err[i])
  731.             j++;
  732.     if (expptr)
  733.         return(mopt || j);
  734.     if (eopt && j)
  735.         return(1);
  736.     return(0);
  737. }
  738.  
  739.  
  740. %}
  741.  
  742. %union    {
  743.     struct item *itemptr;
  744.     int ival;
  745.     char *cval;
  746.     }
  747.  
  748. %token <cval> STRING
  749. %token <itemptr> NOOPERAND
  750. %token <itemptr> ARITHC
  751. %token ADD
  752. %token <itemptr> LOGICAL
  753. %token <itemptr> BIT
  754. %token CALL
  755. %token <itemptr> INCDEC
  756. %token <itemptr> DJNZ
  757. %token EX
  758. %token <itemptr> IM
  759. %token PHASE
  760. %token DEPHASE
  761. %token <itemptr> IN
  762. %token JP
  763. %token <itemptr> JR
  764. %token LD
  765. %token <itemptr> OUT
  766. %token <itemptr> PUSHPOP
  767. %token <itemptr> RET
  768. %token <itemptr> SHIFT
  769. %token <itemptr> RST
  770. %token <itemptr> REGNAME
  771. %token <itemptr> ACC
  772. %token <itemptr> C
  773. %token <itemptr> RP
  774. %token <itemptr> HL
  775. %token <itemptr> INDEX
  776. %token <itemptr> AF
  777. %token <itemptr> SP
  778. %token <itemptr> MISCREG
  779. %token F
  780. %token <itemptr> COND
  781. %token <itemptr> SPCOND
  782. %token <ival> NUMBER
  783. %token <itemptr> UNDECLARED
  784. %token END
  785. %token ORG
  786. %token DEFB
  787. %token DEFS
  788. %token DEFW
  789. %token EQU
  790. %token DEFL
  791. %token <itemptr> LABEL
  792. %token <itemptr> EQUATED
  793. %token <itemptr> WASEQUATED
  794. %token <itemptr> DEFLED
  795. %token <itemptr> MULTDEF
  796. %token <ival> MOD
  797. %token <ival> SHL
  798. %token <ival> SHR
  799. %token <ival> NOT
  800. %token IF
  801. %token ENDIF
  802. %token <itemptr> ARGPSEUDO
  803. %token <itemptr> LIST
  804. %token <itemptr> MINMAX
  805. %token MACRO
  806. %token <itemptr> MNAME
  807. %token <itemptr> OLDMNAME
  808. %token ARG
  809. %token ENDM
  810. %token MPARM
  811. %token <ival> ONECHAR
  812. %token <ival> TWOCHAR
  813.  
  814. %type <itemptr> label.part symbol
  815. %type <ival> reg evenreg realreg mem pushable bcdesp bcdehlsp mar condition
  816. %type <ival> spcondition parenexpr expression lxexpression
  817.  
  818. %left '|' '^'
  819. %left '&'
  820. %nonassoc NOT
  821. %left '+' '-'
  822. %left '*' '/' MOD SHL SHR
  823. %left UNARY
  824. %%
  825.  
  826. %{
  827. char  *cp;
  828. int  i;
  829. %}
  830.  
  831. program:
  832.     statements
  833. |
  834.     error    {    error("file bad");    }
  835. ;
  836.  
  837.  
  838. statements:
  839.     statement
  840. |
  841.     statements statement
  842. |
  843.     statements error    {
  844.         fprintf(stderr,"statement error\n");
  845.         err[fflag]++;
  846.         quoteflag = 0;
  847.         while(yychar != '\n' && yychar != '\0') yychar = yylex();
  848.         list(dollarsign);
  849.         yyclearin;yyerrok;
  850.     }
  851. ;
  852.  
  853.  
  854. statement:
  855.     label.part '\n'    { 
  856.         if ($1) list(dollarsign);
  857.         else  list1();
  858.     }
  859. |
  860.     label.part operation '\n' {
  861.         list(dollarsign);
  862.     }
  863. |
  864.     symbol EQU expression '\n' {
  865.         switch($1->i_token) {
  866.         case UNDECLARED: case WASEQUATED:
  867.             $1->i_token = EQUATED;
  868.             $1->i_value = $3;
  869.             break;
  870.         default:
  871.             err[mflag]++;
  872.             $1->i_token = MULTDEF;
  873.         }
  874.         list($3);
  875.     }
  876. |
  877.     symbol DEFL expression '\n' {
  878.         switch($1->i_token) {
  879.         case UNDECLARED: case DEFLED:
  880.             $1->i_token = DEFLED;
  881.             $1->i_value = $3;
  882.             break;
  883.         default:
  884.             err[mflag]++;
  885.             $1->i_token = MULTDEF;
  886.         }
  887.         list($3);
  888.     }
  889. |
  890.     symbol MINMAX expression ',' expression '\n' {
  891.         switch ($1->i_token) {
  892.         case UNDECLARED: case DEFLED:
  893.             $1->i_token = DEFLED;
  894.             if ($2->i_value)    /* max */
  895.                 list($1->i_value = ($3 > $5? $3:$5));
  896.             else list($1->i_value = ($3 < $5? $3:$5));
  897.             break;
  898.         default:
  899.             err[mflag]++;
  900.             $1->i_token = MULTDEF;
  901.             list($1->i_value);
  902.         }
  903.     }
  904. |
  905.     IF expression '\n' {
  906.         if (ifptr >= ifstmax)
  907.             error("Too many ifs");
  908.         else {
  909.             if (pass2) {
  910.                 *++ifptr = *expifp++;
  911.                 if (*ifptr != !(yypv[2].ival)) err[pflag]++;
  912.             } else {
  913.                 if (expifp >= expifmax)
  914.                     error("Too many ifs!");
  915.                 *expifp++ = !(yypv[2].ival);
  916.                 *++ifptr = !(yypv[2].ival);
  917.             }
  918.         }
  919.         saveopt = fopt;
  920.         fopt = 1;
  921.         list(yypv[2].ival);
  922.         fopt = saveopt;
  923.     }
  924. |
  925.     ENDIF '\n' {
  926.         if (ifptr == ifstack) err[bflag]++;
  927.         else --ifptr;
  928.         list1();
  929.     }
  930. |
  931.     label.part END '\n' {
  932.         list(dollarsign);
  933.         peekc = 0;
  934.     }
  935. |
  936.     label.part END expression '\n' {
  937.         xeq_flag++;
  938.         xeq = $3;
  939.         list($3);
  940.         peekc = 0;
  941.     }
  942. |
  943.     label.part DEFS expression '\n' {
  944.         if ($3 < 0) err[vflag]++;
  945.         list(dollarsign);
  946.         if ($3) {
  947.             flushbin();
  948.             dollarsign += $3;
  949.             olddollar = dollarsign;
  950.         }
  951.     }
  952. |
  953.     ARGPSEUDO arg_on ARG  arg_off '\n' {
  954.         list1();
  955.         switch ($1->i_value) {
  956.  
  957.         case 0:        /* title */
  958.             lineptr = linebuf;
  959.             cp = tempbuf;
  960.             title = titlespace;
  961.             while ((*title++ = *cp++) && (title < &titlespace[TITLELEN]));
  962.             *title = 0;
  963.             title = titlespace;
  964.             break;
  965.  
  966.         case 1:        /* rsym */
  967.             if (pass2) break;
  968.             insymtab(tempbuf);
  969.             break;
  970.  
  971.         case 2:        /* wsym */
  972.             writesyms = malloc(strlen(tempbuf)+1);
  973.             strcpy(writesyms, tempbuf);
  974.             break;
  975.         case 3:        /* include file */
  976.             next_source(tempbuf) ;
  977.             break ;
  978.         }
  979.     }
  980. |
  981.     ARGPSEUDO arg_on '\n' arg_off {
  982.         fprintf(stderr,"ARGPSEUDO error\n");
  983.         err[fflag]++;
  984.         list(dollarsign);
  985.     }
  986. |
  987.     LIST '\n' {
  988.         if ($1 != (struct item *) -1) $<ival>2 = 1;
  989.         goto dolopt; }
  990. |
  991.     LIST expression '\n' {
  992.     dolopt:
  993.         linecnt++;
  994.         if (pass2) {
  995.             lineptr = linebuf;
  996.             switch ($1->i_value) {
  997.             case 0:    /* list */
  998.                 if ($2 < 0) lstoff = 1;
  999.                 if ($2 > 0) lstoff = 0;
  1000.                 break;
  1001.  
  1002.             case 1:    /* eject */
  1003.                 if ($2) eject();
  1004.                 break;
  1005.  
  1006.             case 2:    /* space */
  1007.                 if ((line + $2) > 60) eject();
  1008.                 else space($2);
  1009.                 break;
  1010.  
  1011.             case 3:    /* elist */
  1012.                 eopt = edef;
  1013.                 if ($2 < 0) eopt = 0;
  1014.                 if ($2 > 0) eopt = 1;
  1015.                 break;
  1016.  
  1017.             case 4:    /* fopt */
  1018.                 fopt = fdef;
  1019.                 if ($2 < 0) fopt = 0;
  1020.                 if ($2 > 0) fopt = 1;
  1021.                 break;
  1022.  
  1023.             case 5:    /* gopt */
  1024.                 gopt = gdef;
  1025.                 if ($2 < 0) gopt = 1;
  1026.                 if ($2 > 0) gopt = 0;
  1027.                 break;
  1028.  
  1029.             case 6: /* mopt */
  1030.                 mopt = mdef;
  1031.                 if ($2 < 0) mopt = 0;
  1032.                 if ($2 > 0) mopt = 1;
  1033.             }
  1034.         }
  1035.     }
  1036. |
  1037.     UNDECLARED MACRO parm.list '\n' {
  1038.         $1->i_token = MNAME;
  1039.         $1->i_value = mfptr;
  1040.         mfseek(mfile, (long)mfptr, 0);
  1041.         list1();
  1042.         mlex() ;
  1043.         parm_number = 0;
  1044.     }
  1045. |
  1046.     OLDMNAME MACRO {
  1047.         $1->i_token = MNAME;
  1048.         while (yychar != ENDM && yychar) {
  1049.             while (yychar != '\n' && yychar)
  1050.                 yychar = yylex();
  1051.             list1();
  1052.             yychar = yylex();
  1053.         }
  1054.         while (yychar != '\n' && yychar) yychar = yylex();
  1055.         list1();
  1056.         yychar = yylex();
  1057.     }
  1058. |
  1059.     label.part MNAME al arg.list '\n' {
  1060.     expand:
  1061.         $2->i_uses++ ;
  1062.         arg_flag = 0;
  1063.         parm_number = 0;
  1064.         list(dollarsign);
  1065.         expptr++;
  1066.         est = est2;
  1067.         est[FLOC] = floc;
  1068.         est[TEMPNUM] = (char *)exp_number++;
  1069.         floc = (char *)($2->i_value);
  1070.         mfseek(mfile, (long)floc, 0);
  1071.     }
  1072. ;
  1073.  
  1074.  
  1075. label.part:
  1076.     /*empty*/
  1077.      {    $$ = NULL;    }
  1078. |
  1079.     symbol ':' {
  1080.         switch($1->i_token) {
  1081.         case UNDECLARED:
  1082.             if (pass2)
  1083.                 err[pflag]++;
  1084.             else {
  1085.                 $1->i_token = LABEL;
  1086.                 $1->i_value = dollarsign;
  1087.             }
  1088.             break;
  1089.         case LABEL:
  1090.             if (!pass2) {
  1091.                 $1->i_token = MULTDEF;
  1092.                 err[mflag]++;
  1093.             } else if ($1->i_value != dollarsign)
  1094.                 err[pflag]++;
  1095.             break;
  1096.         default:
  1097.             err[mflag]++;
  1098.             $1->i_token = MULTDEF;
  1099.         }
  1100.     }
  1101. ;
  1102.  
  1103.  
  1104. operation:
  1105.     NOOPERAND
  1106.         { emit1($1->i_value, 0, 0, 1); }
  1107. |
  1108.     JP expression
  1109.         { emit(3, 0303, $2, $2 >> 8);    }
  1110. |
  1111.     CALL expression
  1112.         {    emit(3, 0315, $2, $2 >> 8);    }
  1113. |
  1114.     RST    expression
  1115.         { if ($2 > 7 || $2 < 0)
  1116.             err[vflag]++;
  1117.         emit(1, $1->i_value + (($2 & 7) << 3));
  1118.     }
  1119. |
  1120.     ADD ACC ',' expression
  1121.         { emit1(0306, 0, $4, 3); }
  1122. |
  1123.     ARITHC ACC ',' expression
  1124.         { emit1(0306 + ($1->i_value << 3), 0, $4, 3); }
  1125. |
  1126.     LOGICAL expression
  1127.         { emit1(0306 | ($1->i_value << 3), 0, $2, 3); }
  1128. |
  1129.     LOGICAL ACC ',' expression    /* -cdk */
  1130.         { emit1(0306 | ($1->i_value << 3), 0, $4, 3); }
  1131. |
  1132.     ADD ACC ',' reg
  1133.         { emit1(0200 + ($4 & 0377), $4, 0, 0); }
  1134. |
  1135.     ARITHC ACC ',' reg
  1136.         { emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); }
  1137. |
  1138.     LOGICAL reg
  1139.         { emit1(0200 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
  1140. |
  1141.     LOGICAL ACC ',' reg        /* -cdk */
  1142.         { emit1(0200 + ($1->i_value << 3) + ($4 & 0377), $4, 0, 0); }
  1143. |
  1144.     SHIFT reg
  1145.         { emit1(0145400 + ($1->i_value << 3) + ($2 & 0377), $2, 0, 0); }
  1146. |
  1147.     INCDEC    reg
  1148.         { emit1($1->i_value + (($2 & 0377) << 3) + 4, $2, 0, 0); }
  1149. |
  1150.     ARITHC HL ',' bcdehlsp
  1151.         { if ($1->i_value == 1)
  1152.                 emit(2,0355,0112+$4);
  1153.             else
  1154.                 emit(2,0355,0102+$4);
  1155.         }
  1156. |
  1157.     ADD mar ',' bcdesp
  1158.         { emitdad($2,$4); }
  1159. |
  1160.     ADD mar ',' mar
  1161.         {
  1162.             if ($2 != $4) {
  1163.                 fprintf(stderr,"ADD mar, mar error\n");
  1164.                 err[fflag]++;
  1165.             }
  1166.             emitdad($2,$4);
  1167.         }
  1168. |
  1169.     INCDEC evenreg
  1170.         { emit1(($1->i_value << 3) + ($2 & 0377) + 3, $2, 0, 1); }
  1171. |
  1172.     PUSHPOP pushable
  1173.         { emit1($1->i_value + ($2 & 0377), $2, 0, 1); }
  1174. |
  1175.     BIT expression ',' reg
  1176.         {
  1177.             if ($2 < 0 || $2 > 7)
  1178.                 err[vflag]++;
  1179.             emit1($1->i_value + (($2 & 7) << 3) + ($4 & 0377), $4, 0, 0);
  1180.         }
  1181. |
  1182.     JP condition ',' expression
  1183.         { emit(3, 0302 + $2, $4, $4 >> 8); }
  1184. |
  1185.     JP '(' mar ')'
  1186.         { emit1(0351, $3, 0, 1); }
  1187. |
  1188.     CALL condition ',' expression
  1189.         { emit(3, 0304 + $2, $4, $4 >> 8); }
  1190. |
  1191.     JR expression
  1192.         { emitjr(030,$2); }
  1193. |
  1194.     JR spcondition ',' expression
  1195.         { emitjr($1->i_value + $2, $4); }
  1196. |
  1197.     DJNZ expression
  1198.         { emitjr($1->i_value, $2); }
  1199. |
  1200.     RET
  1201.         { emit(1, $1->i_value); }
  1202. |
  1203.     RET condition
  1204.         { emit(1, 0300 + $2); }
  1205. |
  1206.     LD reg ',' reg
  1207.         {
  1208.             if (($2 & 0377) == 6 && ($4 & 0377) == 6) {
  1209.                 fprintf(stderr,"LD reg, reg error\n");
  1210.                 err[fflag]++;
  1211.             }
  1212.             emit1(0100 + (($2 & 7) << 3) + ($4 & 7),$2 | $4, 0, 0);
  1213.         }
  1214. |
  1215.     LD reg ',' expression
  1216.         { emit1(6 + (($2 & 0377) << 3), $2, $4, 2); }
  1217. |
  1218.     LD reg ',' '(' RP ')'
  1219.         {    if ($2 != 7) {
  1220.                 fprintf(stderr,"LD reg, (RP) error\n");
  1221.                 err[fflag]++;
  1222.             }
  1223.             else emit(1, 012 + $5->i_value);
  1224.         }
  1225. |
  1226.     LD reg ',' parenexpr
  1227.         {
  1228.             if ($2 != 7) {
  1229.                 fprintf(stderr,"LD reg, (expr) error\n");
  1230.                 err[fflag]++;
  1231.             }
  1232.             else emit(3, 072, $4, $4 >> 8);
  1233.         }
  1234. |
  1235.     LD '(' RP ')' ',' ACC
  1236.         { emit(1, 2 + $3->i_value); }
  1237. |
  1238.     LD parenexpr ',' ACC
  1239.         { emit(3, 062, $2, $2 >> 8); }
  1240. |
  1241.     LD reg ',' MISCREG
  1242.         {
  1243.             if ($2 != 7) {
  1244.                 fprintf(stderr,"LD reg, MISCREG error\n");
  1245.                 err[fflag]++;
  1246.             }
  1247.             else emit(2, 0355, 0127 + $4->i_value);
  1248.         }
  1249. |
  1250.     LD MISCREG ',' ACC
  1251.         { emit(2, 0355, 0107 + $2->i_value); }
  1252. |
  1253.     LD evenreg ',' lxexpression
  1254.         { emit1(1 + ($2 & 060), $2, $4, 5); }
  1255. |
  1256.     LD evenreg ',' parenexpr
  1257.         {
  1258.             if (($2 & 060) == 040)
  1259.                 emit1(052, $2, $4, 5);
  1260.             else
  1261.                 emit(4, 0355, 0113 + $2, $4, $4 >> 8);
  1262.         }
  1263. |
  1264.     LD parenexpr ',' evenreg
  1265.         {
  1266.             if (($4 & 060) == 040)
  1267.                 emit1(042, $4, $2, 5);
  1268.             else
  1269.                 emit(4, 0355, 0103 + $4, $2, $2 >> 8);
  1270.         }
  1271. |
  1272.     LD evenreg ',' mar
  1273.         {
  1274.             if ($2 != 060) {
  1275.                 fprintf(stderr,"LD evenreg error\n");
  1276.                 err[fflag]++;
  1277.             }
  1278.             else
  1279.                 emit1(0371, $4, 0, 1);
  1280.         }
  1281. |
  1282.     EX RP ',' HL
  1283.         {
  1284.             if ($2->i_value != 020) {
  1285.                 fprintf(stderr,"EX RP, HL error\n");
  1286.                 err[fflag]++;
  1287.             }
  1288.             else
  1289.                 emit(1, 0353);
  1290.         }
  1291. |
  1292.     EX AF ',' AF setqf '\'' clrqf
  1293.         { emit(1, 010); }
  1294. |
  1295.     EX '(' SP ')' ',' mar
  1296.         { emit1(0343, $6, 0, 1); }
  1297. |
  1298.     IN realreg ',' parenexpr
  1299.         {
  1300.             if ($2 != 7) {
  1301.                 fprintf(stderr,"IN reg, (expr) error\n");
  1302.                 err[fflag]++;
  1303.             }
  1304.             else    {
  1305.                 if ($4 < 0 || $4 > 255)
  1306.                     err[vflag]++;
  1307.                 emit(2, $1->i_value, $4);
  1308.             }
  1309.         }
  1310. |
  1311.     IN realreg ',' '(' C ')'
  1312.         { emit(2, 0355, 0100 + ($2 << 3)); }
  1313. |
  1314.     IN F ',' '(' C ')'
  1315.         { emit(2, 0355, 0160); }
  1316. |
  1317.     OUT parenexpr ',' ACC
  1318.         {
  1319.             if ($2 < 0 || $2 > 255)
  1320.                 err[vflag]++;
  1321.             emit(2, $1->i_value, $2);
  1322.         }
  1323. |
  1324.     OUT '(' C ')' ',' realreg
  1325.         { emit(2, 0355, 0101 + ($6 << 3)); }
  1326. |
  1327.     IM expression
  1328.         {
  1329.             if ($2 > 2 || $2 < 0)
  1330.                 err[vflag]++;
  1331.             else
  1332.                 emit(2, $1->i_value >> 8, $1->i_value + (($2 + ($2 > 0)) << 3));
  1333.         }
  1334. |
  1335.     PHASE expression
  1336.         {
  1337.             if (phaseflag) {
  1338.                 err[oflag]++;
  1339.             } else {
  1340.                 phaseflag = 1;
  1341.                 phdollar = dollarsign;
  1342.                 dollarsign = $2;
  1343.                 phbegin = dollarsign;
  1344.             }
  1345.         }
  1346. |
  1347.     DEPHASE
  1348.         {
  1349.             if (!phaseflag) {
  1350.                 err[oflag]++;
  1351.             } else {
  1352.                 phaseflag = 0;
  1353.                 dollarsign = phdollar + dollarsign - phbegin;
  1354.             }
  1355.         }
  1356. |
  1357.     ORG expression
  1358.         {
  1359.             if (phaseflag) {
  1360.                 err[oflag]++;
  1361.                 dollarsign = phdollar + dollarsign - phbegin;
  1362.                 phaseflag = 0;
  1363.             }
  1364.             if ($2-dollarsign) {
  1365.                 flushbin();
  1366.                 olddollar = $2;
  1367.                 dollarsign = $2;
  1368.             }
  1369.         }
  1370. |
  1371.     DEFB db.list
  1372. |
  1373.     DEFW dw.list
  1374. |
  1375.     ENDM
  1376. ;
  1377.  
  1378.  
  1379. parm.list:
  1380. |
  1381.     parm.element
  1382. |
  1383.     parm.list ',' parm.element
  1384. ;
  1385.  
  1386.  
  1387. parm.element:
  1388.     UNDECLARED
  1389.         {
  1390.             $1->i_token = MPARM;
  1391.             if (parm_number >= PARMMAX)
  1392.                 error("Too many parameters");
  1393.             $1->i_value = parm_number++;
  1394.         }
  1395. ;
  1396.  
  1397.  
  1398. arg.list:
  1399.     /* empty */
  1400. |
  1401.     arg.element
  1402. |
  1403.     arg.list ',' arg.element
  1404. ;
  1405.  
  1406.  
  1407. arg.element:
  1408.     ARG
  1409.         {
  1410.             cp = malloc(strlen(tempbuf)+1);
  1411.             est2[parm_number++] = cp;
  1412.             strcpy(cp, tempbuf);
  1413.         }
  1414. ;
  1415. reg:
  1416.     realreg
  1417. |
  1418.     mem
  1419. ;
  1420. realreg:
  1421.     REGNAME
  1422.         {
  1423.             $$ = $1->i_value;
  1424.         }
  1425. |
  1426.     ACC
  1427.         {
  1428.             $$ = $1->i_value;
  1429.         }
  1430. |
  1431.     C
  1432.         {
  1433.             $$ = $1->i_value;
  1434.         }
  1435. ;
  1436. mem:
  1437.     '(' HL ')'
  1438.         {
  1439.             $$ = 6;
  1440.         }
  1441. |
  1442.     '(' INDEX expression ')'
  1443.         {
  1444.             disp = $3;
  1445.             $$ = ($2->i_value & 0177400) | 6;
  1446.         }
  1447. |
  1448.     '(' INDEX ')'
  1449.         {
  1450.             disp = 0;
  1451.             $$ = ($2->i_value & 0177400) | 6;
  1452.         }
  1453. ;
  1454. evenreg:
  1455.     bcdesp
  1456. |
  1457.     mar
  1458. ;
  1459. pushable:
  1460.     RP
  1461.         {
  1462.             $$ = $1->i_value;
  1463.         }
  1464. |
  1465.     AF
  1466.         {
  1467.             $$ = $1->i_value;
  1468.         }
  1469. |
  1470.     mar
  1471. ;
  1472. bcdesp:
  1473.     RP
  1474.         {
  1475.             $$ = $1->i_value;
  1476.         }
  1477. |
  1478.     SP
  1479.         {
  1480.             $$ = $1->i_value;
  1481.         }
  1482. ;
  1483. bcdehlsp:
  1484.     bcdesp
  1485. |
  1486.     HL
  1487.         {
  1488.             $$ = $1->i_value;
  1489.         }
  1490. ;
  1491. mar:
  1492.     HL
  1493.         {
  1494.             $$ = $1->i_value;
  1495.         }
  1496. |
  1497.     INDEX
  1498.         {
  1499.             $$ = $1->i_value;
  1500.         }
  1501. ;
  1502. condition:
  1503.     spcondition
  1504. |
  1505.     COND
  1506.         {
  1507.             $$ = $1->i_value;
  1508.         }
  1509. ;
  1510. spcondition:
  1511.     SPCOND
  1512.         {
  1513.             $$ = $1->i_value;
  1514.         }
  1515. |
  1516.     C
  1517.         {    $$ = 030;    }
  1518. ;
  1519. db.list:
  1520.     db.list.element
  1521. |
  1522.     db.list ',' db.list.element
  1523. ;
  1524. db.list.element:
  1525.     TWOCHAR
  1526.         {
  1527.             emit(2, $1, $1>>8);
  1528.         }
  1529. |
  1530.     STRING
  1531.         {
  1532.             cp = $1;
  1533.             while (*cp != '\0')
  1534.                 emit(1,*cp++);
  1535.         }
  1536. |
  1537.     expression
  1538.         {
  1539.             if ($1 < -128 || $1 > 255)
  1540.                     err[vflag]++;
  1541.             emit(1, $1 & 0377);
  1542.         }
  1543. ;
  1544.  
  1545.  
  1546. dw.list:
  1547.     dw.list.element
  1548. |
  1549.     dw.list ',' dw.list.element
  1550. ;
  1551.  
  1552.  
  1553. dw.list.element:
  1554.     expression
  1555.         {
  1556.             emit(2, $1, $1>>8);
  1557.         }
  1558. ;
  1559.  
  1560.  
  1561.  
  1562. lxexpression:
  1563.     expression
  1564. |
  1565.     TWOCHAR
  1566. ;
  1567.  
  1568. parenexpr:
  1569.     '(' expression ')'
  1570.         {    $$ = $2;    }
  1571. ;
  1572.  
  1573. expression:
  1574.     error
  1575.         {
  1576.             err[eflag]++;
  1577.             $$ = 0;
  1578.         }
  1579. |
  1580.     LABEL
  1581.         {    $$ = $1->i_value; $1->i_uses++ ;    }
  1582. |
  1583.     NUMBER
  1584. |
  1585.     ONECHAR
  1586. |
  1587.     EQUATED
  1588.         {    $$ = $1->i_value;    }
  1589. |
  1590.     WASEQUATED
  1591.         {    $$ = $1->i_value;    }
  1592. |
  1593.     DEFLED
  1594.         {    $$ = $1->i_value;    }
  1595. |
  1596.     '$'
  1597.         {    $$ = dollarsign;    }
  1598. |
  1599.     UNDECLARED
  1600.         {
  1601.             err[uflag]++;
  1602.             $$ = 0;
  1603.         }
  1604. |
  1605.     MULTDEF
  1606.         {    $$ = $1->i_value;    }
  1607. |
  1608.     expression '+' expression
  1609.         {    $$ = $1 + $3;    }
  1610. |
  1611.     expression '-' expression
  1612.         {    $$ = $1 - $3;    }
  1613. |
  1614.     expression '/' expression
  1615.         {    $$ = $1 / $3;    }
  1616. |
  1617.     expression '*' expression
  1618.         {    $$ = $1 * $3;    }
  1619. |
  1620.     expression MOD expression
  1621.         {    $$ = $1 % $3;    }
  1622. |
  1623.     expression '&' expression
  1624.         {    $$ = $1 & $3;    }
  1625. |
  1626.     expression '|' expression
  1627.         {    $$ = $1 | $3;    }
  1628. |
  1629.     expression '^' expression
  1630.         {    $$ = $1 ^ $3;    }
  1631. |
  1632.     expression SHL expression
  1633.         {    $$ = $1 << $3;    }
  1634. |
  1635.     expression SHR expression
  1636.         {    $$ = (($1 >> 1) & 077777) >> ($3 - 1);    }
  1637. |
  1638.     '[' expression ']'
  1639.         {    $$ = $2;    }
  1640. |
  1641.     NOT expression
  1642.         {    $$ = ~$2;    }
  1643. |
  1644.     '+' expression %prec UNARY
  1645.         {    $$ = $2;    }
  1646. |
  1647.     '-' expression %prec UNARY
  1648.         {    $$ = -$2;    }
  1649. ;
  1650.  
  1651. symbol:
  1652.     UNDECLARED
  1653. |
  1654.     LABEL
  1655. |
  1656.     MULTDEF
  1657. |
  1658.     EQUATED
  1659. |
  1660.     WASEQUATED
  1661. |
  1662.     DEFLED
  1663. ;
  1664.  
  1665.  
  1666. al:
  1667.     {
  1668.         if (expptr >= MAXEXP)
  1669.             error("Macro expansion level");
  1670.         est2 = (char **) malloc((PARMMAX +4) * sizeof(char *));
  1671.         expstack[expptr] = (char *)est2 ;
  1672.         for (i=0; i<PARMMAX; i++)
  1673.             est2[i] = 0;
  1674.         arg_flag++;
  1675.     }
  1676. ;
  1677.  
  1678.  
  1679. arg_on:
  1680.     {    arg_flag++;    }
  1681. ;
  1682.  
  1683. arg_off:
  1684.         {    arg_flag = 0;    }
  1685. ;
  1686.  
  1687. setqf:
  1688.         {    quoteflag++;    }
  1689. ;
  1690.  
  1691. clrqf:
  1692.         {    quoteflag = 0;    }
  1693.  
  1694. ;
  1695.  
  1696. %%
  1697. /*extern int    yylval;*/
  1698.  
  1699. #define F_END    0
  1700. #define OTHER    1
  1701. #define SPACE    2
  1702. #define DIGIT    3
  1703. #define LETTER    4
  1704. #define STARTER 5
  1705.  
  1706.  
  1707. /*
  1708.  *  This is the table of character classes.  It is used by the lexical
  1709.  *  analyser. (yylex())
  1710.  */
  1711. char    charclass[] = {
  1712.     F_END,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,
  1713.     OTHER,    SPACE,    OTHER,    OTHER,    OTHER,    SPACE,    OTHER,    OTHER,
  1714.     OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,
  1715.     OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,
  1716.     SPACE,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,
  1717.     OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,
  1718.     DIGIT,    DIGIT,    DIGIT,    DIGIT,    DIGIT,    DIGIT,    DIGIT,    DIGIT,
  1719.     DIGIT,    DIGIT,    OTHER,    OTHER,    OTHER,    OTHER,    OTHER,    STARTER,
  1720.     STARTER,LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1721.     LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1722.     LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1723.     LETTER, LETTER, LETTER, OTHER,    OTHER,    OTHER,    OTHER,    LETTER,
  1724.     OTHER,    LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1725.     LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1726.     LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER,
  1727.     LETTER, LETTER, LETTER, OTHER,    OTHER,    OTHER,    OTHER,    OTHER,
  1728. };
  1729.  
  1730.  
  1731. /*
  1732.  *  the following table tells which characters are parts of numbers.
  1733.  *  The entry is non-zero for characters which can be parts of numbers.
  1734.  */
  1735. char    numpart[] = {
  1736.     0,    0,    0,    0,    0,    0,    0,    0,
  1737.     0,    0,    0,    0,    0,    0,    0,    0,
  1738.     0,    0,    0,    0,    0,    0,    0,    0,
  1739.     0,    0,    0,    0,    0,    0,    0,    0,
  1740.     0,    0,    0,    0,    0,    0,    0,    0,
  1741.     0,    0,    0,    0,    0,    0,    0,    0,
  1742.     '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
  1743.     '8',    '9',    0,    0,    0,    0,    0,    0,
  1744.     0,    'A',    'B',    'C',    'D',    'E',    'F',    0,
  1745.     'H',    0,    0,    0,    0,    0,    0,    'O',
  1746.     0,    'Q',    0,    0,    0,    0,    0,    0,
  1747.     0,    0,    0,    0,    0,    0,    0,    0,
  1748.     0,    'a',    'b',    'c',    'd',    'e',    'f',    0,
  1749.     'h',    0,    0,    0,    0,    0,    0,    'o',
  1750.     0,    'q',    0,    0,    0,    0,    0,    0,
  1751.     0,    0,    0,    0,    0,    0,    0,    0,
  1752.     0};
  1753.  
  1754.  
  1755.  
  1756.  
  1757. /*
  1758.  *  the following table is a list of assembler mnemonics;
  1759.  *  for each mnemonic the associated machine-code bit pattern
  1760.  *  and symbol type are given.
  1761.  */
  1762. struct    item    keytab[] = {
  1763.     "a",    7,    ACC,    0,
  1764.     "adc",    1,    ARITHC,    0,
  1765.     "add",    0,    ADD,    0,
  1766.     "af",    060,    AF,    0,
  1767.     "and",    4,    LOGICAL,    0,
  1768.     "ascii",0,    DEFB,    0,
  1769.     "b",    0,    REGNAME,    0,
  1770.     "bc",    0,    RP,    0,
  1771.     "bit",    0145500,BIT,    0,
  1772.     "block",0,    DEFS,    0,
  1773.     "byte",    0,    DEFB,    0,
  1774.     "c",    1,    C,    0,
  1775.     "call", 0315,    CALL,    0,
  1776.     "ccf",    077,    NOOPERAND,    0,
  1777.     "cmp",    7,    LOGICAL,    0,        /* -cdk */
  1778.     "cp",    7,    LOGICAL,    0,
  1779.     "cpd",    0166651,NOOPERAND,    0,
  1780.     "cpdr",    0166671,NOOPERAND,    0,
  1781.     "cpi",    0166641,NOOPERAND,    0,
  1782.     "cpir",    0166661,NOOPERAND,    0,
  1783.     "cpl",    057,    NOOPERAND,    0,
  1784.     "d",    2,    REGNAME,    0,
  1785.     "daa",    0047,    NOOPERAND,    0,
  1786.     "de",    020,    RP,    0,
  1787.     "dec",    1,    INCDEC,    0,
  1788.     "defb",    0,    DEFB,    0,
  1789.     "defl",0,    DEFL,    0,
  1790.     "defs",    0,    DEFS,    0,
  1791.     "defw",    0,    DEFW,    0,
  1792.     "dephase",    0,    DEPHASE,    0,
  1793.     "di",    0363,    NOOPERAND,    0,
  1794.     "djnz",    020,    DJNZ,    0,
  1795.     "e",    3,    REGNAME,    0,
  1796.     "ei",    0373,    NOOPERAND,    0,
  1797.     "eject",1,    LIST,    0,
  1798.     "elist",3,    LIST,    0,
  1799.     "end",    0,    END,    0,
  1800.     "endif",0,    ENDIF,    0,
  1801.     "endm", 0,    ENDM,    0,
  1802.     "equ",    0,    EQU,    0,
  1803.     "ex",    0,    EX,    0,
  1804.     "exx",    0331,    NOOPERAND,    0,
  1805.     "f",    0,    F,    0,
  1806.     "flist",4,    LIST,    0,
  1807.     "glist",5,    LIST,    0,
  1808.     "h",    4,    REGNAME,    0,
  1809.     "halt",    0166,    NOOPERAND,    0,
  1810.     "hl",    040,    HL,    0,
  1811.     "i",    0,    MISCREG,    0,
  1812.     "if",    0,    IF,    0,
  1813.     "im",    0166506,IM,    0,
  1814.     "in",    0333,    IN,    0,
  1815.     "inc",    0,    INCDEC,    0,
  1816.     "include", 3,    ARGPSEUDO,    0,
  1817.     "ind",    0166652,NOOPERAND,    0,
  1818.     "indr",    0166672,NOOPERAND,    0,
  1819.     "ini",    0166642,NOOPERAND,    0,
  1820.     "inir",    0166662,NOOPERAND,    0,
  1821.     "ix",    0156440,INDEX,    0,
  1822.     "iy",    0176440,INDEX,    0,
  1823.     "jmp",    0303,    JP,    0,        /* -cdk */
  1824.     "jp",    0303,    JP,    0,
  1825.     "jr",    040,    JR,    0,
  1826.     "l",    5,    REGNAME,    0,
  1827.     "ld",    0,    LD,    0,
  1828.     "ldd",    0166650,NOOPERAND,    0,
  1829.     "lddr",    0166670,NOOPERAND,    0,
  1830.     "ldi",    0166640,NOOPERAND,    0,
  1831.     "ldir",    0166660,NOOPERAND,    0,
  1832.     "list",    0,    LIST,    0,
  1833.     "m",    070,    COND,    0,
  1834.     "macro",0,    MACRO,    0,
  1835.     "max",    1,    MINMAX,    0,
  1836.     "min",    0,    MINMAX,    0,
  1837.     "mlist",6,    LIST,    0,
  1838.     "mod",    0,    MOD,    0,
  1839.     "nc",    020,    SPCOND,    0,
  1840.     "neg",    0166504,NOOPERAND,    0,
  1841.     "nolist",-1,    LIST,    0,
  1842.     "nop",    0,    NOOPERAND,    0,
  1843.     "not",    0,    NOT,    0,
  1844.     "nv",    040,    COND,    0,
  1845.     "nz",    0,    SPCOND,    0,
  1846.     "or",    6,    LOGICAL,    0,
  1847.     "org",    0,    ORG,    0,
  1848.     "otdr",0166673,NOOPERAND,    0,
  1849.     "otir",0166663,NOOPERAND,    0,
  1850.     "out",    0323,    OUT,    0,
  1851.     "outd",    0166653,NOOPERAND,    0,
  1852.     "outi",    0166643,NOOPERAND,    0,
  1853.     "p",    060,    COND,    0,
  1854.     "pe",    050,    COND,    0,
  1855.     "phase",    0,    PHASE,    0,
  1856.     "po",    040,    COND,    0,
  1857.     "pop",    0301,    PUSHPOP,    0,
  1858.     "push", 0305,    PUSHPOP,    0,
  1859.     "r",    010,    MISCREG,    0,
  1860.     "res",    0145600,BIT,    0,
  1861.     "ret",    0311,    RET,    0,
  1862.     "reti",    0166515,NOOPERAND,    0,
  1863.     "retn",    0166505,NOOPERAND,    0,
  1864.     "rl",    2,    SHIFT,    0,
  1865.     "rla",    027,    NOOPERAND,    0,
  1866.     "rlc",    0,    SHIFT,    0,
  1867.     "rlca",    07,    NOOPERAND,    0,
  1868.     "rld",    0166557,NOOPERAND,    0,
  1869.     "rr",    3,    SHIFT,    0,
  1870.     "rra",    037,    NOOPERAND,    0,
  1871.     "rrc",    1,    SHIFT,    0,
  1872.     "rrca",    017,    NOOPERAND,    0,
  1873.     "rrd",    0166547,NOOPERAND,    0,
  1874.     "rst",    0307,    RST,    0,
  1875.     "rsym",    1,    ARGPSEUDO,    0,
  1876.     "sbc",    3,    ARITHC,    0,
  1877.     "scf",    067,    NOOPERAND,    0,
  1878.     "set",    0145700,BIT,    0,
  1879.     "shl",    0,    SHL,    0,
  1880.     "shr",    0,    SHR,    0,
  1881.     "sla",    4,    SHIFT,    0,
  1882.     "sp",    060,    SP,    0,
  1883.     "space",2,    LIST,    0,
  1884.     "sra",    5,    SHIFT,    0,
  1885.     "srl",    7,    SHIFT,    0,
  1886.     "sub",    2,    LOGICAL,    0,
  1887.     "title",0,    ARGPSEUDO,    0,
  1888.     "v",    050,    COND,    0,
  1889.     "word",    0,    DEFW,    0,
  1890.     "wsym",    2,    ARGPSEUDO,    0,
  1891.     "xor",    5,    LOGICAL,    0,
  1892.     "z",    010,    SPCOND,    0,
  1893. };
  1894.  
  1895. /*
  1896.  *  user-defined items are tabulated in the following table.
  1897.  */
  1898.  
  1899. struct item    itemtab[ITEMTABLESIZE];
  1900. struct item    *itemmax = &itemtab[ITEMTABLESIZE];
  1901.  
  1902.  
  1903.  
  1904.  
  1905.  
  1906. /*
  1907.  *  lexical analyser, called by yyparse.
  1908.  */
  1909. yylex()
  1910. {
  1911.     register char    c;
  1912.     register char *p;
  1913.     register int    radix;
  1914.     int  limit;
  1915.  
  1916.     if (arg_flag)
  1917.         return(getarg());
  1918. loop switch(charclass[c = nextchar()]) {
  1919.     case F_END:
  1920.         if (expptr) {
  1921.             popsi();
  1922.             continue;
  1923.         } else return(0);
  1924.  
  1925.     case SPACE:
  1926.         break;
  1927.     case LETTER:
  1928.     case STARTER:
  1929.         p = tempbuf;
  1930.         do {
  1931.             if (p >= tempmax)
  1932.                 error(symlong);
  1933.             *p++ = (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
  1934.             while    ((c = nextchar()) == '$')
  1935.                 ;
  1936.         } while    (charclass[c]==LETTER || charclass[c]==DIGIT);
  1937.         if (p - tempbuf > MAXSYMBOLSIZE)
  1938.             p = tempbuf + MAXSYMBOLSIZE;
  1939.         *p++ = '\0';
  1940.         peekc = c;
  1941.         return(tokenofitem(UNDECLARED));
  1942.     case DIGIT:
  1943.         if (*ifptr) return(skipline(c));
  1944.         p = tempbuf;
  1945.         do    {
  1946.             if (p >= tempmax)
  1947.                 error(symlong);
  1948.             *p++ = (c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c;
  1949.             while    ((c = nextchar()) == '$');
  1950.             }
  1951.             while(numpart[c]);
  1952.         peekc = c;
  1953.         *p-- = '\0';
  1954.         switch(*p)    {
  1955.             case 'o':
  1956.             case 'q':
  1957.                 radix = 8;
  1958.                 limit = 020000;
  1959.                 *p = '\0';
  1960.                 break;
  1961.             case 'd':
  1962.                 radix = 10;
  1963.                 limit = 3276;
  1964.                 *p = '\0';
  1965.                 break;
  1966.             case 'h':
  1967.                 radix = 16;
  1968.                 limit = 010000;
  1969.                 *p = '\0';
  1970.                 break;
  1971.             case 'b':
  1972.                 radix = 2;
  1973.                 limit = 077777;
  1974.                 *p = '\0';
  1975.                 break;
  1976.             default:
  1977.                 radix = 10;
  1978.                 limit = 3276;
  1979.                 p++;
  1980.                 break;
  1981.             }
  1982.  
  1983.         /*
  1984.          *  tempbuf now points to the number, null terminated
  1985.          *  with radix 'radix'.
  1986.          */
  1987.         yylval.ival = 0;
  1988.         p = tempbuf;
  1989.         do    {
  1990.             c = *p - (*p > '9' ? ('a' - 10) : '0');
  1991.             if (c >= radix)
  1992.                 {
  1993.                 err[iflag]++;
  1994.                 yylval.ival = 0;
  1995.                 break;
  1996.                 }
  1997.             if (yylval.ival < limit ||
  1998.                 (radix == 10 && yylval.ival == 3276 && c < 8) ||
  1999.                 (radix == 2 && yylval.ival == limit))
  2000.                 yylval.ival = yylval.ival * radix + c;
  2001.             else {
  2002.                 err[vflag]++;
  2003.                 yylval.ival = 0;
  2004.                 break;
  2005.                 }
  2006.             }
  2007.             while(*++p != '\0');
  2008.         return(NUMBER);
  2009.     default:
  2010.         if (*ifptr)
  2011.             return(skipline(c));
  2012.         switch(c) {
  2013.         case ';':
  2014.             return(skipline(c));
  2015.         case '\'':
  2016.             if (quoteflag) return('\'');
  2017.             p = tempbuf;
  2018.             p[1] = 0;
  2019.             do    switch(c = nextchar())    {
  2020.             case '\0':
  2021.             case '\n':
  2022.                 err[bflag]++;
  2023.                 goto retstring;
  2024.             case '\'':
  2025.                 if ((c = nextchar()) != '\'') {
  2026.                 retstring:
  2027.                     peekc = c;
  2028.                     *p = '\0';
  2029.                     if ((p-tempbuf) >2) {
  2030.                         yylval.cval = tempbuf;
  2031.                         return(STRING);
  2032.                     } else if (p-tempbuf == 2)    {
  2033.                         p = tempbuf;
  2034.                         yylval.ival = *p++ ;
  2035.                         yylval.ival |= *p<<8;
  2036.                         return(TWOCHAR);
  2037.                     } else    {
  2038.                         p = tempbuf;
  2039.                         yylval.ival = *p++;
  2040.                         return(ONECHAR);
  2041.                     }
  2042.                 }
  2043.             default:
  2044.                 *p++ = c;
  2045.             } while (p < tempmax);
  2046.             /*
  2047.              *  if we break out here, our string is longer than
  2048.              *  our input line
  2049.              */
  2050.             error("string buffer overflow");
  2051.         default:
  2052.             return(c);
  2053.         }
  2054.     }
  2055. }
  2056.  
  2057. /*
  2058.  *  return the token associated with the string pointed to by
  2059.  *  tempbuf.  if no token is associated with the string, associate
  2060.  *  deftoken with the string and return deftoken.
  2061.  *  in either case, cause yylval to point to the relevant
  2062.  *  symbol table entry.
  2063.  */
  2064.  
  2065. tokenofitem(deftoken)
  2066. int    deftoken;
  2067. {
  2068.     register  char *p;
  2069.     register struct item *    ip;
  2070.     register  i;
  2071.     int  r, l, u, hash;
  2072.  
  2073.  
  2074. #ifdef T_DEBUG
  2075.     fputs("'tokenofitem entry'    ", stderr) ;
  2076.     fputs(tempbuf, stderr) ;
  2077. #endif
  2078.     /*
  2079.      *  binary search
  2080.      */
  2081.     l = 0;
  2082.     u = (sizeof keytab/sizeof keytab[0])-1;
  2083.     while (l <= u) {
  2084.         i = (l+u)/2;
  2085.         ip = &keytab[i];
  2086.         if ((r = strcmp(tempbuf, ip->i_string)) == 0)
  2087.             goto found;
  2088.         if (r < 0)
  2089.             u = i-1;
  2090.         else
  2091.             l = i+1;
  2092.     }
  2093.  
  2094.     /*
  2095.      *  hash into item table
  2096.      */
  2097.     hash = 0;
  2098.     p = tempbuf;
  2099.     while (*p) hash += *p++;
  2100.     hash %= ITEMTABLESIZE;
  2101.     ip = &itemtab[hash];
  2102.  
  2103.     loop {
  2104.         if (ip->i_token == 0)
  2105.             break;
  2106.         if (strcmp(tempbuf, ip->i_string) == 0)
  2107.             goto found;
  2108.         if (++ip >= itemmax)
  2109.             ip = itemtab;
  2110.     }
  2111.  
  2112.     if (!deftoken) {
  2113.         i = 0 ;
  2114.         goto token_done ;
  2115.     }
  2116.     if (++nitems > ITEMTABLESIZE-20)
  2117.         error("item table overflow");
  2118.     ip->i_string = malloc(strlen(tempbuf)+1);
  2119.     ip->i_token = deftoken;
  2120.     ip->i_uses = 0 ;
  2121.     strcpy(ip->i_string, tempbuf);
  2122.  
  2123. found:
  2124.     if (*ifptr) {
  2125.         if (ip->i_token == ENDIF) {
  2126.             i = ENDIF ;
  2127.             goto token_done ;
  2128.         }
  2129.         if (ip->i_token == IF) {
  2130.             if (ifptr >= ifstmax)
  2131.                 error("Too many ifs");
  2132.             else *++ifptr = 1;
  2133.         }
  2134.         i = skipline(' ');
  2135.         goto token_done ;
  2136.     }
  2137.     yylval.itemptr = ip;
  2138.     i = ip->i_token;
  2139. token_done:
  2140. #ifdef T_DEBUG
  2141.     fputs("\t'tokenofitem exit'\n", stderr) ;
  2142. #endif
  2143.     return(i) ;
  2144. }
  2145.  
  2146.  
  2147. /*
  2148.  *  interchange two entries in the item table -- used by qsort
  2149.  */
  2150. interchange(i, j)
  2151. {
  2152.     register  struct item *fp, *tp;
  2153.     struct item temp;
  2154.  
  2155.     fp = &itemtab[i];
  2156.     tp = &itemtab[j];
  2157.     temp.i_string = fp->i_string;
  2158.     temp.i_value = fp->i_value;
  2159.     temp.i_token = fp->i_token;
  2160.     temp.i_uses = fp->i_uses;
  2161.  
  2162.     fp->i_string = tp->i_string;
  2163.     fp->i_value = tp->i_value;
  2164.     fp->i_token = tp->i_token;
  2165.     fp->i_uses = tp->i_uses;
  2166.  
  2167.     tp->i_string = temp.i_string;
  2168.     tp->i_value = temp.i_value;
  2169.     tp->i_token = temp.i_token;
  2170.     tp->i_uses = temp.i_uses;
  2171. }
  2172.  
  2173.  
  2174.  
  2175. /*
  2176.  *  quick sort -- used by putsymtab to sort the symbol table
  2177.  */
  2178. qsort(m, n)
  2179. {
  2180.     register  i, j;
  2181.  
  2182.     if (m < n) {
  2183.         i = m;
  2184.         j = n+1;
  2185.         loop {
  2186.             do i++; while(strcmp(itemtab[i].i_string,
  2187.                     itemtab[m].i_string) < 0);
  2188.             do j--; while(strcmp(itemtab[j].i_string,
  2189.                     itemtab[m].i_string) > 0);
  2190.             if (i < j) interchange(i, j); else break;
  2191.         }
  2192.         interchange(m, j);
  2193.         qsort(m, j-1);
  2194.         qsort(j+1, n);
  2195.     }
  2196. }
  2197.  
  2198.  
  2199.  
  2200. /*
  2201.  *  get the next character
  2202.  */
  2203. nextchar()
  2204. {
  2205.     register int c, ch;
  2206.     static  char  *earg;
  2207.     char *getlocal();
  2208.  
  2209.     if (peekc != -1) {
  2210.         c = peekc;
  2211.         peekc = -1;
  2212.         return(c);
  2213.     }
  2214.  
  2215. start:
  2216.     if (earg) {
  2217.         if (*earg)
  2218.             return(addtoline(*earg++));
  2219.         earg = 0;
  2220.     }
  2221.  
  2222.     if (expptr) {
  2223.         if ((ch = getm()) == '\1') {    /*  expand argument  */
  2224.             ch = getm() - 'A';
  2225.             if (ch >= 0 && ch < PARMMAX && est[ch])
  2226.                 earg = est[ch];
  2227.             goto start;
  2228.         }
  2229.         if (ch == '\2') {    /*  local symbol  */
  2230.             ch = getm() - 'A';
  2231.             if (ch >= 0 && ch < PARMMAX && est[ch]) {
  2232.                 earg = est[ch];
  2233.                 goto start;
  2234.             }
  2235.             earg = getlocal(ch, (int)est[TEMPNUM]);
  2236.             goto start;
  2237.         }
  2238.  
  2239.         return(addtoline(ch));
  2240.     }
  2241.     ch = getc(now_file) ;
  2242.     /* if EOF, check for include file */
  2243.     if (ch == EOF) {
  2244.         while (ch == EOF && now_in) {
  2245.             fclose(fin[now_in]) ;
  2246.             free(src_name[now_in]) ;
  2247.             now_file = fin[--now_in] ;
  2248.             ch = getc(now_file) ;
  2249.         }
  2250.         if (linein[now_in] < 0) {
  2251.             lstoff = 1 ;
  2252.             linein[now_in] = -linein[now_in] ;
  2253.         } else {
  2254.             lstoff = 0 ;
  2255.         }
  2256.         if (pass2 && iflist()) {
  2257.             lineout() ;
  2258.             fprintf(fout, "**** %s ****\n", src_name[now_in]) ;
  2259.         }
  2260.     }
  2261.     if (ch == '\n')
  2262.         linein[now_in]++ ;
  2263.  
  2264.     return(addtoline(ch)) ;
  2265. }
  2266.  
  2267.  
  2268. /*
  2269.  *  skip to rest of the line -- comments and if skipped lines
  2270.  */
  2271. skipline(ac)
  2272. {
  2273.     register  c;
  2274.  
  2275.     c = ac;
  2276.     while (c != '\n' && c != '\0')
  2277.         c = nextchar();
  2278.     return('\n');
  2279. }
  2280.  
  2281.  
  2282.  
  2283. main(argc, argv)
  2284. char  **argv;
  2285. {
  2286.     register  struct item *ip;
  2287.     register  i;
  2288.     int  files;
  2289. #ifdef DBUG
  2290.     extern  yydebug;
  2291. #endif
  2292.  
  2293.     fout = stdout ;
  2294.     fin[0] = stdin ;
  2295.     now_file = stdin ;
  2296.     files = 0;
  2297.  
  2298.     for (i=1; i<argc; i++) {
  2299.         if (*argv[i] == '-') while (*++argv[i]) switch(*argv[i]) {
  2300.  
  2301.         case 'b':    /*  no binary  */
  2302.             bopt = 0;
  2303.             continue;
  2304.  
  2305. #ifdef DBUG
  2306.         case 'd':    /*  debug  */
  2307.             yydebug++;
  2308.             continue;
  2309. #endif
  2310.  
  2311.         case 'e':    /*  error list only  */
  2312.             eopt = 0;
  2313.             edef = 0;
  2314.             continue;
  2315.  
  2316.         case 'f':    /*  print if skipped lines  */
  2317.             fopt++;
  2318.             fdef++;
  2319.             continue;
  2320.  
  2321.         case 'g':    /*  do not list extra code  */
  2322.             gopt = 0;
  2323.             gdef = 0;
  2324.             continue;
  2325.  
  2326.         case 'i':    /* do not list include files */
  2327.             iopt = 1 ;
  2328.             continue ;
  2329.  
  2330.         case 'l':    /*  no list  */
  2331.             lopt++;
  2332.             continue;
  2333.  
  2334.         case 'L':    /*  force listing of everything */
  2335.             lston++;
  2336.             continue;
  2337.  
  2338.         case 'm':    /*  print macro expansions  */
  2339.             mdef++;
  2340.             mopt++;
  2341.             continue;
  2342.  
  2343.         case 'n':    /*  put line numbers off */
  2344.             nopt-- ;
  2345.             continue;
  2346.  
  2347.         case 'o':    /*  list to standard output  */
  2348.             oopt++;
  2349.             continue;
  2350.  
  2351.         case 'p':    /*  put out four \n's for eject */
  2352.             popt-- ;
  2353.             continue;
  2354.  
  2355.         case 's':    /*  don't produce a symbol list  */
  2356.             sopt++;
  2357.             continue;
  2358.  
  2359.         case 't':
  2360.             topt = 0;
  2361.             continue;
  2362.  
  2363.         default:    /*  error  */
  2364.             error("Unknown option");
  2365.  
  2366.         } else if (files++ == 0) {
  2367.             sourcef = argv[i];
  2368.             strcpy(src, sourcef);
  2369.             suffix(src,".z");
  2370.             if ((now_file = fopen(src, "r")) == NULL)
  2371.                 error("Cannot open source file");
  2372.             now_in = 0 ;
  2373.             fin[now_in] = now_file ;
  2374.             src_name[now_in] = src ;
  2375.         } else if (files)
  2376.             error("Too many arguments");
  2377.     }
  2378.  
  2379.  
  2380.     if (files == 0)
  2381.         error("No source file");
  2382.     strcpy(bin, sourcef);
  2383.     suffix(bin,".hex");
  2384.     if (bopt)
  2385. #ifdef MSDOS
  2386.         if (( fbuf = fopen(bin, "wb")) == NULL)
  2387. #else
  2388.         if (( fbuf = fopen(bin, "w")) == NULL)
  2389. #endif
  2390.             error("Cannot create binary file");
  2391.     if (!lopt && !oopt) {
  2392.         strcpy(listf, sourcef);
  2393.         suffix(listf,".lst");
  2394.         if ((fout = fopen(listf, "w")) == NULL)
  2395.             error("Cannot create list file");
  2396.     } else
  2397.         fout = stdout ;
  2398.     strcpy(mtmp, sourcef);
  2399.     suffix(mtmp,".tmp");
  2400. #ifdef MSDOS
  2401.     mfile = mfopen(mtmp,"w+b") ;
  2402. #else
  2403.     mfile = mfopen(mtmp,"w+") ;
  2404. #endif
  2405.     if (mfile == NULL) {
  2406.         error("Cannot create temp file");
  2407.     }
  2408.     /*unlink(mtmp);*/
  2409.  
  2410.     /*
  2411.      *  get the time
  2412.      */
  2413.     time(&now);
  2414.     timp = ctime(&now);
  2415.     timp[16] = 0;
  2416.     timp[24] = 0;
  2417.  
  2418.     title = sourcef;
  2419.     /*
  2420.      * pass 1
  2421.      */
  2422. #ifdef DEBUG
  2423.     fputs("DEBUG-pass 1\n", stderr) ;
  2424. #endif
  2425.     setvars();
  2426.     yyparse();
  2427.     pass2++;
  2428.     ip = &itemtab[-1];
  2429.     while (++ip < itemmax) {
  2430.         /* reset use count */
  2431.         ip->i_uses = 0 ;
  2432.  
  2433.         /* set macro names, equated and defined names */
  2434.         switch    (ip->i_token) {
  2435.         case MNAME:
  2436.             ip->i_token = OLDMNAME;
  2437.             break;
  2438.  
  2439.         case EQUATED:
  2440.             ip->i_token = WASEQUATED;
  2441.             break;
  2442.  
  2443.         case DEFLED:
  2444.             ip->i_token = UNDECLARED;
  2445.             break;
  2446.         }
  2447.     }
  2448.     setvars();
  2449.     fseek(now_file, (long)0, 0);
  2450.  
  2451. #ifdef DEBUG
  2452.     fputs("DEBUG- pass 2\n", stderr) ;
  2453. #endif
  2454.     yyparse();
  2455.  
  2456.  
  2457.     if (bopt) {
  2458.         flushbin();
  2459.         putc(':', fbuf);
  2460.         if (xeq_flag) {
  2461.             puthex(0, fbuf);
  2462.             puthex(xeq >> 8, fbuf);
  2463.             puthex(xeq, fbuf);
  2464.             puthex(1, fbuf);
  2465.             puthex(255-(xeq >> 8)-xeq, fbuf);
  2466.         } else
  2467.             for    (i = 0; i < 10; i++)
  2468.                 putc('0', fbuf);
  2469.         putc('\n', fbuf);
  2470.         fflush(fbuf);
  2471.     }
  2472.  
  2473.     if (!lopt)
  2474.         fflush(fout);
  2475.     if (writesyms)
  2476.         outsymtab(writesyms);
  2477.     if (eopt)
  2478.         erreport();
  2479.     if (!lopt && !sopt)
  2480.         putsymtab();
  2481.     if (!lopt) {
  2482.         eject();
  2483.         fflush(fout);
  2484.     }
  2485.     exit(0);
  2486. }
  2487.  
  2488.  
  2489. /*
  2490.  *  set some data values before each pass
  2491.  */
  2492. setvars()
  2493. {
  2494.     register  i;
  2495.  
  2496.     peekc = -1;
  2497.     linein[now_in] = linecnt = 0;
  2498.     exp_number = 0;
  2499.     emitptr = emitbuf;
  2500.     lineptr = linebuf;
  2501.     ifptr = ifstack;
  2502.     expifp = expif;
  2503.     *ifptr = 0;
  2504.     dollarsign = 0;
  2505.     olddollar = 0;
  2506.     phaseflag = 0;
  2507.     for (i=0; i<FLAGS; i++) err[i] = 0;
  2508. }
  2509.  
  2510.  
  2511.  
  2512. /*
  2513.  *  print out an error message and die
  2514.  */
  2515. error(as)
  2516. char *as;
  2517. {
  2518.  
  2519.     *linemax = 0;
  2520.     fprintf(fout, "%s\n", linebuf);
  2521.     fflush(fout);
  2522.     fprintf(stderr, "%s\n", as) ;
  2523.     exit(1);
  2524. }
  2525.  
  2526.  
  2527.  
  2528. /*
  2529.  *  output the symbol table
  2530.  */
  2531. putsymtab()
  2532. {
  2533.     register  struct item *tp, *fp;
  2534.     int  i, j, k, t, rows;
  2535.     char c, c1 ;
  2536.  
  2537.     if (!nitems)
  2538.         return;
  2539.  
  2540.     /* compact the table so unused and UNDECLARED entries are removed */
  2541.     tp = &itemtab[-1];
  2542.     for (fp = itemtab; fp<itemmax; fp++) {
  2543.         if (fp->i_token == UNDECLARED) {
  2544.             nitems--;
  2545.             continue;
  2546.         }
  2547.         if (fp->i_token == 0)
  2548.             continue;
  2549.         tp++;
  2550.         if (tp != fp) {
  2551.             tp->i_string = fp->i_string;
  2552.             tp->i_value = fp->i_value;
  2553.             tp->i_token = fp->i_token;
  2554.             tp->i_uses = fp->i_uses ;
  2555.         }
  2556.     }
  2557.  
  2558.     tp++;
  2559.     tp->i_string = "{";
  2560.  
  2561.     /*  sort the table */
  2562.     qsort(0, nitems-1);
  2563.  
  2564.     title = "**  Symbol Table  **";
  2565.  
  2566.     rows = (nitems+3) / 4;
  2567.     if (rows+5+line > 60)
  2568.         eject();
  2569.     lineout();
  2570.     fprintf(fout,"\n\n\nSymbol Table:\n\n") ;
  2571.     line += 4;
  2572.  
  2573.     for (i=0; i<rows; i++) {
  2574.         for(j=0; j<4; j++) {
  2575.             k = rows*j+i;
  2576.             if (k < nitems) {
  2577.                 tp = &itemtab[k];
  2578.                 t = tp->i_token;
  2579.                 c = ' ' ;
  2580.                 if (t == EQUATED || t == DEFLED)
  2581.                     c = '=' ;
  2582.                 if (tp->i_uses == 0)
  2583.                     c1 = '+' ;
  2584.                 else
  2585.                     c1 = ' ' ;
  2586.                 fprintf(fout, "%-15s%c%4x%c    ",
  2587.                     tp->i_string, c, tp->i_value & 0xffff, c1);
  2588.             }
  2589.         }
  2590.         lineout();
  2591.         putc('\n', fout);
  2592.     }
  2593. }
  2594.  
  2595.  
  2596.  
  2597.  
  2598. /*
  2599.  *  put out error report
  2600.  */
  2601. erreport()
  2602. {
  2603.     register i, numerr;
  2604.  
  2605.     if (line > 50) eject();
  2606.     lineout();
  2607.     numerr = 0;
  2608.     for (i=0; i<FLAGS; i++) numerr += keeperr[i];
  2609.     if (numerr) {
  2610.         fputs("\n\n\nError report:\n\n", fout);
  2611.         fprintf(fout, "%6d errors\n", numerr);
  2612.         line += 5;
  2613.     } else {
  2614.         fputs("\n\n\nStatistics:\n", fout);
  2615.         line += 3;
  2616.     }
  2617.  
  2618.     for (i=0; i<FLAGS; i++)
  2619.         if (keeperr[i]) {
  2620.             lineout();
  2621.             fprintf(fout, "%6d %c -- %s error\n",
  2622.                 keeperr[i], errlet[i], errname[i]);
  2623.         }
  2624.  
  2625.     if (line > 55) eject();
  2626.     lineout();
  2627.     fprintf(fout, "\n%6d\tsymbols\n", nitems);
  2628.     fprintf(fout, "%6d\tbytes\n", nbytes);
  2629.     line += 2;
  2630.     if (mfptr) {
  2631.         if (line > 53) eject();
  2632.         lineout();
  2633.         fprintf(fout, "\n%6d\tmacro calls\n", exp_number);
  2634.         fprintf(fout, "%6d\tmacro bytes\n", mfptr);
  2635.         fprintf(fout, "%6d\tinvented symbols\n", invented/2);
  2636.         line += 3;
  2637.     }
  2638. }
  2639.  
  2640.  
  2641. /*
  2642.  *  lexical analyser for macro definition
  2643.  */
  2644. mlex()
  2645. {
  2646.     register  char  *p;
  2647.     register  c;
  2648.     int  t;
  2649.  
  2650.     /*
  2651.      *  move text onto macro file, changing formal parameters
  2652.      */
  2653. #ifdef    M_DEBUG
  2654.     fprintf(stderr,"enter 'mlex'\t") ;
  2655. #endif
  2656.     inmlex++;
  2657.  
  2658.     c = nextchar();
  2659. loop {
  2660.     switch(charclass[c]) {
  2661.  
  2662.     case DIGIT:
  2663.         while (numpart[c]) {
  2664.             putm(c);
  2665.             c = nextchar();
  2666.         }
  2667.         continue;
  2668.  
  2669.     case STARTER:
  2670.     case LETTER:
  2671.         t = 0;
  2672.         p = tempbuf+MAXSYMBOLSIZE+2;
  2673.         do {
  2674.             if (p >= tempmax)
  2675.                 error(symlong);
  2676.             *p++ = c;
  2677.             if (t < MAXSYMBOLSIZE)
  2678.                 tempbuf[t++] = (c >= 'A' && c <= 'Z')  ?
  2679.                     c+'a'-'A' : c;
  2680.             c = nextchar();
  2681.         } while (charclass[c]==LETTER || charclass[c]==DIGIT);
  2682.  
  2683.         tempbuf[t] = 0;
  2684.         *p++ = '\0';
  2685.         p = tempbuf+MAXSYMBOLSIZE+2;
  2686.         t = tokenofitem(0);
  2687.         if (t != MPARM) while (*p) putm(*p++);
  2688.         else {
  2689.             if (*(yylval.itemptr->i_string) == '?') putm('\2');
  2690.             else putm('\1');
  2691.             putm(yylval.itemptr->i_value + 'A');
  2692.         }
  2693.         if (t == ENDM) goto done;
  2694.         continue;
  2695.  
  2696.     case F_END:
  2697.         if (expptr) {
  2698.             popsi();
  2699.             c = nextchar();
  2700.             continue;
  2701.         }
  2702.  
  2703.         goto done;
  2704.  
  2705.     default:
  2706.         if (c == '\n') {
  2707.             linecnt++;
  2708.         }
  2709.         if (c != '\1') putm(c);
  2710.         c = nextchar();
  2711.     }
  2712. }
  2713.  
  2714.     /*
  2715.      *  finish off the file entry
  2716.      */
  2717. done:
  2718.     while(c != EOF && c != '\n' && c != '\0') c = nextchar();
  2719.     linecnt++;
  2720.     putm('\n');
  2721.     putm('\n');
  2722.     putm(0);
  2723.  
  2724.     for (c=0; c<ITEMTABLESIZE; c++)
  2725.         if (itemtab[c].i_token == MPARM) {
  2726.             itemtab[c].i_token = UNDECLARED;
  2727.         }
  2728.     inmlex = 0;
  2729. #ifdef    M_DEBUG
  2730.     fprintf(stderr,"exit 'mlex'\n") ;
  2731. #endif
  2732. }
  2733.  
  2734.  
  2735.  
  2736. /*
  2737.  *  lexical analyser for the arguments of a macro call
  2738.  */
  2739. getarg()
  2740. {
  2741.     register int c;
  2742.     register char *p;
  2743.     static int comma;
  2744.  
  2745.     *tempbuf = 0;
  2746.     yylval.cval = tempbuf;
  2747.     while(charclass[c = nextchar()] == SPACE);
  2748.  
  2749.     switch(c) {
  2750.  
  2751.     case '\0':
  2752.         popsi();
  2753.     case '\n':
  2754.     case ';':
  2755.         comma = 0;
  2756.         return(skipline(c));
  2757.  
  2758.     case ',':
  2759.         if (comma) {
  2760.             comma = 0;
  2761.             return(',');
  2762.         }
  2763.         else {
  2764.             comma++;
  2765.             return(ARG);
  2766.         }
  2767.  
  2768.     case '\'':
  2769.         p = tempbuf;
  2770.         do switch (c = nextchar()) {
  2771.             case '\0':
  2772.             case '\n':
  2773.                 peekc = c;
  2774.                 *p = 0;
  2775.                 err[bflag]++;
  2776.                 return(ARG);
  2777.             case '\'':
  2778.                 if ((c = nextchar()) != '\'') {
  2779.                     peekc = c;
  2780.                     *p = '\0';
  2781.                     comma++;
  2782.                     return(ARG);
  2783.                 }
  2784.             default:
  2785.                 *p++ = c;
  2786.         } while (p < tempmax);
  2787.         error(symlong);
  2788.  
  2789.     default:  /* unquoted string */
  2790.         p = tempbuf;
  2791.         peekc = c;
  2792.         do switch(c = nextchar()) {
  2793.             case '\0':
  2794.             case '\n':
  2795.             case '\t':
  2796.             case ' ':
  2797.             case ',':
  2798.                 peekc = c;
  2799.                 *p = '\0';
  2800.                 comma++;
  2801.                 return(ARG);
  2802.             default:
  2803.                 *p++ = c;
  2804.         } while (p < tempmax);
  2805.     }
  2806. }
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812. /*
  2813.  *  add a suffix to a string
  2814.  */
  2815. suffix(str,suff)
  2816. char *str,*suff;
  2817. {
  2818.     while(*str != '\0' && *str != '.')
  2819.         *str++;
  2820.     strcpy(str, suff);
  2821. }
  2822.  
  2823.  
  2824.  
  2825.  
  2826. /*
  2827.  *  put out a byte to the macro file, keeping the offset
  2828.  */
  2829. putm(c)
  2830. char c ;
  2831. {
  2832.     mfptr++;
  2833.     mfputc(c,mfile) ;
  2834. }
  2835.  
  2836.  
  2837.  
  2838. /*
  2839.  *  get a byte from the macro file
  2840.  */
  2841. getm()
  2842. {
  2843.     int ch;
  2844.  
  2845.     floc++;
  2846.     ch = mfgetc(mfile) ;
  2847.     if (ch == EOF) {
  2848.         ch = 0;
  2849.         fprintf(stderr,"bad macro read\n") ;
  2850.     }
  2851.     return(ch);
  2852. }
  2853.  
  2854.  
  2855.  
  2856. /*
  2857.  *  pop standard input
  2858.  */
  2859. popsi()
  2860. {
  2861.     register  i;
  2862.  
  2863.     for (i=0; i<PARMMAX; i++) {
  2864.         if (est[i]) free(est[i]);
  2865.     }
  2866.     floc = est[FLOC];
  2867.     free(est);
  2868.     expptr--;
  2869.     est = expptr ? (char **) expstack[expptr-1] : (char **) 0;
  2870.     mfseek(mfile, (long)floc, 0);
  2871.     if (lineptr > linebuf) lineptr--;
  2872. }
  2873.  
  2874.  
  2875.  
  2876. /*
  2877.  *  return a unique name for a local symbol
  2878.  *  c is the parameter number, n is the macro number.
  2879.  */
  2880.  
  2881. char *
  2882. getlocal(c, n)
  2883. int c,n;
  2884. {
  2885. static char local_label[10];
  2886.     invented++;
  2887.     if (c >= 26)
  2888.         c += 'a' - '0';
  2889.     sprintf(local_label, "?%c%04d", c+'a', n) ;
  2890.     return(local_label);
  2891. }
  2892.  
  2893.  
  2894.  
  2895. /*
  2896.  *  read in a symbol table
  2897.  */
  2898. insymtab(name)
  2899. char *name;
  2900. {
  2901.     register struct stab *t;
  2902.     int  s, i, sfile;
  2903.  
  2904.     t = (struct stab *) tempbuf;
  2905. #ifdef MSDOS
  2906.     if ((sfile = open(name, O_RDONLY | O_BINARY)) < 0)
  2907. #else
  2908.     if ((sfile = open(name, O_RDONLY)) < 0)
  2909. #endif
  2910.         return;
  2911.     read(sfile, (char *)t, sizeof *t);
  2912.     if (t->t_value != SYMMAJIC)
  2913.         return;
  2914.  
  2915.     s = t->t_token;
  2916.     for (i=0; i<s; i++) {
  2917.         read(sfile, (char *)t, sizeof *t);
  2918.         if (tokenofitem(UNDECLARED) != UNDECLARED)
  2919.             continue;
  2920.         yylval.itemptr->i_token = t->t_token;
  2921.         yylval.itemptr->i_value = t->t_value;
  2922.         if (t->t_token == MACRO)
  2923.             yylval.itemptr->i_value += mfptr;
  2924.     }
  2925.  
  2926.     while ((s = read(sfile, tempbuf, TEMPBUFSIZE)) > 0) {
  2927.         mfptr += s;
  2928.         mfwrite(tempbuf, 1, s, mfile) ;
  2929.     }
  2930. }
  2931.  
  2932.  
  2933.  
  2934. /*
  2935.  *  write out symbol table
  2936.  */
  2937. outsymtab(name)
  2938. char *name;
  2939. {
  2940.     register struct stab *t;
  2941.     register struct item *ip;
  2942.     int  i, sfile;
  2943.  
  2944.     t = (struct stab *) tempbuf;
  2945.     if ((sfile = creat(name, 0644)) < 0)
  2946.         return;
  2947.     for (ip=itemtab; ip<itemmax; ip++) {
  2948.         if (ip->i_token == UNDECLARED) {
  2949.             ip->i_token = 0;
  2950.             nitems--;
  2951.         }
  2952.     }
  2953.  
  2954.     copyname(title, (char *)t);
  2955.     t->t_value = SYMMAJIC;
  2956.     t->t_token = nitems;
  2957.     write(sfile, (char *)t, sizeof *t);
  2958.  
  2959.     for (ip=itemtab; ip<itemmax; ip++) {
  2960.         if (ip->i_token != 0) {
  2961.             t->t_token = ip->i_token;
  2962.             t->t_value = ip->i_value;
  2963.             copyname(ip->i_string, (char *)t);
  2964.             write(sfile, (char *)t, sizeof *t);
  2965.         }
  2966.     }
  2967.  
  2968.     mfseek(mfile, (long)0, 0);
  2969.     while((i = mfread(tempbuf, 1, TEMPBUFSIZE, mfile) ) > 0)
  2970.         write(sfile, tempbuf, i);
  2971. }
  2972.  
  2973.  
  2974.  
  2975. /*
  2976.  *  copy a name into the symbol file
  2977.  */
  2978. copyname(st1, st2)
  2979. char *st1, *st2;
  2980. {
  2981.     register  char  *s1, *s2;
  2982.     register  i;
  2983.  
  2984.     i = (MAXSYMBOLSIZE+2) & ~01;
  2985.     s1 = st1;
  2986.     s2 = st2;
  2987.  
  2988.     while(*s2++ = *s1++) i--;
  2989.     while(--i > 0) *s2++ = '\0';
  2990. }
  2991.  
  2992. /* get the next source file */
  2993. next_source(sp)
  2994. char *sp ;
  2995. {
  2996.  
  2997.     if(now_in == NEST_IN -1)
  2998.         error("Too many nested includes") ;
  2999.     if ((now_file = fopen(sp, "r")) == NULL) {
  3000.         char ebuf[100] ;
  3001.         sprintf(ebuf,"Can't open include file: %s", sp) ;
  3002.         error(ebuf) ;
  3003.     }
  3004.     if (pass2 && iflist()) {
  3005.         lineout() ;
  3006.         fprintf(fout, "**** %s ****\n",sp) ;
  3007.     }
  3008.  
  3009.     /* save the list control flag with the current line number */
  3010.     if (lstoff)
  3011.         linein[now_in] = - linein[now_in] ;
  3012.  
  3013.     /* no list if include files are turned off */
  3014.     lstoff |= iopt ;
  3015.  
  3016.     /* save the new file descriptor. */
  3017.     fin[++now_in] = now_file ;
  3018.     /* start with line 0 */
  3019.     linein[now_in] = 0 ;
  3020.     /* save away the file name */
  3021.     src_name[now_in] = malloc(strlen(sp)+1) ;
  3022.     strcpy(src_name[now_in],sp) ;
  3023. }
  3024. SHAR_EOF
  3025. if test 50295 -ne "`wc -c < 'zmac.y'`"
  3026. then
  3027.     echo shar: error transmitting "'zmac.y'" '(should have been 50295 characters)'
  3028. fi
  3029. chmod +x 'zmac.y'
  3030. fi # end of overwriting check
  3031. echo shar: extracting "'mio.c'" '(2326 characters)'
  3032. if test -f 'mio.c'
  3033. then
  3034.     echo shar: will not over-write existing file "'mio.c'"
  3035. else
  3036. cat << \SHAR_EOF > 'mio.c'
  3037. /*
  3038.  * mio.c - Colin Kelley  1-18-87
  3039.  *   routines to emulate temporary file handling with memory instead
  3040.  *
  3041.  */
  3042.  
  3043. #include <stdio.h>
  3044. #define MALLOC_SIZE 10000
  3045.  
  3046. unsigned char *malloc(), *realloc();
  3047.  
  3048. static unsigned char *mhead;        /* pointer to start of malloc()d area */
  3049. static unsigned char *mend;            /* pointer to current (just beyond) EOF*/
  3050. static unsigned char *mptr;            /* pointer to current position */
  3051. static unsigned int msize;            /* size of chunk mhead points to */
  3052.  
  3053. FILE *
  3054. mfopen(filename,mode)
  3055. char *filename,*mode;
  3056. {
  3057.     if ((mhead = malloc(MALLOC_SIZE)) == 0) {
  3058.         msize = 0;
  3059.         return (0);
  3060.     }
  3061.     msize = MALLOC_SIZE;
  3062.     mend = mptr = mhead;
  3063.     return ((FILE *)1);                /* not used */
  3064. }
  3065.  
  3066. mfclose(f)
  3067. FILE *f;
  3068. {
  3069.     if (mhead) {
  3070.         free(mhead);
  3071.         return (0);
  3072.     }
  3073.     else
  3074.         return (-1);
  3075. }
  3076.  
  3077. unsigned int
  3078. mfputc(c,f)
  3079. unsigned int c;
  3080. FILE *f;
  3081. {
  3082. register unsigned char *p;
  3083.     while (mptr >= mhead + msize) {
  3084.         if ((p = realloc(mhead,msize+MALLOC_SIZE)) == (unsigned char *)-1) {
  3085.             fputs("mio: out of memory\n",stderr);
  3086.             return (-1);
  3087.         }
  3088.         else {
  3089.             msize += MALLOC_SIZE;
  3090.             mptr = (unsigned char *) (p + (unsigned int)(mptr - mhead));
  3091.             mhead = p;
  3092.         }
  3093.     }
  3094.     *mptr = c & 255;
  3095.     mend = ++mptr;
  3096.     return c;
  3097. }
  3098.  
  3099. unsigned int
  3100. mfgetc(f)
  3101. FILE *f;
  3102. {
  3103.     if (mptr >= mend)        /* no characters left */
  3104.         return (-1);
  3105.     else
  3106.         return (*mptr++);
  3107. }
  3108.  
  3109. mfseek(f,loc,origin)
  3110. FILE *f;
  3111. long loc;
  3112. int origin;
  3113. {
  3114.     if (origin != 0) {
  3115.         fputs("mseek() only implemented with 0 origin",stderr);
  3116.         return (-1);
  3117.     }
  3118.     mptr = mhead + loc;
  3119.     return (0);
  3120. }
  3121.  
  3122. mfread(ptr, size, nitems,f)
  3123. char *ptr;
  3124. unsigned int size, nitems;
  3125. FILE *f;
  3126. {
  3127. register unsigned int i = 0;
  3128.     while (i < nitems) {
  3129.         if ((mptr + size) > mend)
  3130.             break;
  3131.         bcopy(mptr,ptr,size);
  3132.         ptr += size;
  3133.         mptr += size;
  3134.         i++;
  3135.     }
  3136.     return (i);
  3137. }
  3138.  
  3139. mfwrite(ptr, size, nitems, f)
  3140. char *ptr;
  3141. int size, nitems;
  3142. FILE *f;
  3143. {
  3144. register unsigned int i = 0;
  3145. register unsigned char *p;
  3146.     while (i < nitems) {
  3147.         while (mptr + size >= mhead + msize) {
  3148.             if ((p = realloc(mhead,msize+MALLOC_SIZE)) == (unsigned char *)-1){
  3149.                 fputs("mio: out of memory\n",stderr);
  3150.                 return (-1);
  3151.             }
  3152.             else {
  3153.                 msize += MALLOC_SIZE;
  3154.                 mptr = (unsigned char *) (p + (unsigned int)(mptr - mhead));
  3155.                 mhead = p;
  3156.             }
  3157.         }
  3158.         if ((mptr + size) > mhead + msize)
  3159.             break;
  3160.         bcopy(ptr,mend,size);
  3161.         ptr += size;
  3162.         mend += size;
  3163.         mptr = mend;
  3164.     }
  3165.     return (i);
  3166. }
  3167. SHAR_EOF
  3168. if test 2326 -ne "`wc -c < 'mio.c'`"
  3169. then
  3170.     echo shar: error transmitting "'mio.c'" '(should have been 2326 characters)'
  3171. fi
  3172. chmod +x 'mio.c'
  3173. fi # end of overwriting check
  3174. echo shar: extracting "'zmac.1'" '(1329 characters)'
  3175. if test -f 'zmac.1'
  3176. then
  3177.     echo shar: will not over-write existing file "'zmac.1'"
  3178. else
  3179. cat << \SHAR_EOF > 'zmac.1'
  3180. .TH ZMAC l 
  3181. .SH NAME
  3182. zmac \- macro cross-assembler for the Zilog Z80 microprocessor
  3183. .SH SYNOPSIS
  3184. zmac [-bdefgilLmnopst] infile
  3185. .SH DESCRIPTION
  3186. The
  3187. .I Zmac
  3188. assembler is modeled after the Intel 8080 macro cross-assembler
  3189. for the Intel 8080 by Ken Borgendale.  The major features are:  Full
  3190. macro capabilities, Conditional assembly, A very flexible set of
  3191. listing options and pseudo-ops, Symbol table output, Error report,
  3192. Elimination of sequential searching, Commenting of source, Facilities
  3193. for system definiton files.
  3194. .PP
  3195. .I Zmac
  3196. assembles the specified input file (default extension .z) and
  3197. produces a .hex output file.  The options are:
  3198. .TP 8
  3199. .B b
  3200. no binary  
  3201. .TP 8
  3202. .B d
  3203. debug  
  3204. .TP 8
  3205. .B e
  3206. error list only  
  3207. .TP 8
  3208. .B f
  3209. print if skipped lines  
  3210. .TP 8
  3211. .B g
  3212. do not list extra code  
  3213. .TP 8
  3214. .B i
  3215. do not list include files 
  3216. .TP 8
  3217. .B l
  3218. no list  
  3219. .TP 8
  3220. .B L
  3221. force listing of everything 
  3222. .TP 8
  3223. .B m
  3224. print macro expansions  
  3225. .TP 8
  3226. .B n
  3227. put line numbers off 
  3228. .TP 8
  3229. .B o
  3230. list to standard output  
  3231. .TP 8
  3232. .B p
  3233. put out four \\n's for eject 
  3234. .TP 8
  3235. .B s
  3236. don't produce a symbol list  
  3237. .TP 8
  3238. .B t
  3239. don't know what this option does
  3240. .SH SEE ALSO
  3241. zdis(l)
  3242. .SH FILES
  3243. Source is in /usr/local/src/zmac directory.
  3244. .SH BUGS
  3245. The man page is incomplete.  If anyone discovers more information about
  3246. using zmac, please consider helping to update the man page.
  3247. SHAR_EOF
  3248. if test 1329 -ne "`wc -c < 'zmac.1'`"
  3249. then
  3250.     echo shar: error transmitting "'zmac.1'" '(should have been 1329 characters)'
  3251. fi
  3252. chmod +x 'zmac.1'
  3253. fi # end of overwriting check
  3254. echo shar: extracting "'zdis.1'" '(526 characters)'
  3255. if test -f 'zdis.1'
  3256. then
  3257.     echo shar: will not over-write existing file "'zdis.1'"
  3258. else
  3259. cat << \SHAR_EOF > 'zdis.1'
  3260. .TH ZDIS l 
  3261. .SH NAME
  3262. zdis \- disassembler for Z80 cross-assembler
  3263. .SH SYNOPSIS
  3264. zdis < infile.hex
  3265. .SH DESCRIPTION
  3266. .I Zdis
  3267. reads a hex file created by
  3268. .I zmac
  3269. and produces a disassembly on stdout.
  3270. .SH SEE ALSO
  3271. zmac(l)
  3272. .SH FILES
  3273. Source is in /usr/local/src/zmac directory.
  3274. .SH BUGS
  3275. Zdis ignores the program counter field in the hex file.  Instead it assumes
  3276. that the hex file has an ORG of 0.
  3277. .sp
  3278. The man page is incomplete.  If anyone discovers more information about
  3279. using zdis, please consider helping to update the man page.
  3280. SHAR_EOF
  3281. if test 526 -ne "`wc -c < 'zdis.1'`"
  3282. then
  3283.     echo shar: error transmitting "'zdis.1'" '(should have been 526 characters)'
  3284. fi
  3285. chmod +x 'zdis.1'
  3286. fi # end of overwriting check
  3287. #    End of shell archive
  3288. exit 0
  3289.  
  3290.